LCOV - code coverage report
Current view: top level - gcc - builtins.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 4518 5272 85.7 %
Date: 2020-04-04 11:58:09 Functions: 191 210 91.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Expand builtin functions.
       2                 :            :    Copyright (C) 1988-2020 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.c instead.  */
      23                 :            : 
      24                 :            : #include "config.h"
      25                 :            : #include "system.h"
      26                 :            : #include "coretypes.h"
      27                 :            : #include "backend.h"
      28                 :            : #include "target.h"
      29                 :            : #include "rtl.h"
      30                 :            : #include "tree.h"
      31                 :            : #include "memmodel.h"
      32                 :            : #include "gimple.h"
      33                 :            : #include "predict.h"
      34                 :            : #include "tm_p.h"
      35                 :            : #include "stringpool.h"
      36                 :            : #include "tree-vrp.h"
      37                 :            : #include "tree-ssanames.h"
      38                 :            : #include "expmed.h"
      39                 :            : #include "optabs.h"
      40                 :            : #include "emit-rtl.h"
      41                 :            : #include "recog.h"
      42                 :            : #include "diagnostic-core.h"
      43                 :            : #include "alias.h"
      44                 :            : #include "fold-const.h"
      45                 :            : #include "fold-const-call.h"
      46                 :            : #include "gimple-ssa-warn-restrict.h"
      47                 :            : #include "stor-layout.h"
      48                 :            : #include "calls.h"
      49                 :            : #include "varasm.h"
      50                 :            : #include "tree-object-size.h"
      51                 :            : #include "tree-ssa-strlen.h"
      52                 :            : #include "realmpfr.h"
      53                 :            : #include "cfgrtl.h"
      54                 :            : #include "except.h"
      55                 :            : #include "dojump.h"
      56                 :            : #include "explow.h"
      57                 :            : #include "stmt.h"
      58                 :            : #include "expr.h"
      59                 :            : #include "libfuncs.h"
      60                 :            : #include "output.h"
      61                 :            : #include "typeclass.h"
      62                 :            : #include "langhooks.h"
      63                 :            : #include "value-prof.h"
      64                 :            : #include "builtins.h"
      65                 :            : #include "stringpool.h"
      66                 :            : #include "attribs.h"
      67                 :            : #include "asan.h"
      68                 :            : #include "internal-fn.h"
      69                 :            : #include "case-cfn-macros.h"
      70                 :            : #include "gimple-fold.h"
      71                 :            : #include "intl.h"
      72                 :            : #include "file-prefix-map.h" /* remap_macro_filename()  */
      73                 :            : #include "gomp-constants.h"
      74                 :            : #include "omp-general.h"
      75                 :            : #include "tree-dfa.h"
      76                 :            : 
      77                 :            : struct target_builtins default_target_builtins;
      78                 :            : #if SWITCHABLE_TARGET
      79                 :            : struct target_builtins *this_target_builtins = &default_target_builtins;
      80                 :            : #endif
      81                 :            : 
      82                 :            : /* Define the names of the builtin function types and codes.  */
      83                 :            : const char *const built_in_class_names[BUILT_IN_LAST]
      84                 :            :   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
      85                 :            : 
      86                 :            : #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
      87                 :            : const char * built_in_names[(int) END_BUILTINS] =
      88                 :            : {
      89                 :            : #include "builtins.def"
      90                 :            : };
      91                 :            : 
      92                 :            : /* Setup an array of builtin_info_type, make sure each element decl is
      93                 :            :    initialized to NULL_TREE.  */
      94                 :            : builtin_info_type builtin_info[(int)END_BUILTINS];
      95                 :            : 
      96                 :            : /* Non-zero if __builtin_constant_p should be folded right away.  */
      97                 :            : bool force_folding_builtin_constant_p;
      98                 :            : 
      99                 :            : static int target_char_cast (tree, char *);
     100                 :            : static rtx get_memory_rtx (tree, tree);
     101                 :            : static int apply_args_size (void);
     102                 :            : static int apply_result_size (void);
     103                 :            : static rtx result_vector (int, rtx);
     104                 :            : static void expand_builtin_prefetch (tree);
     105                 :            : static rtx expand_builtin_apply_args (void);
     106                 :            : static rtx expand_builtin_apply_args_1 (void);
     107                 :            : static rtx expand_builtin_apply (rtx, rtx, rtx);
     108                 :            : static void expand_builtin_return (rtx);
     109                 :            : static enum type_class type_to_class (tree);
     110                 :            : static rtx expand_builtin_classify_type (tree);
     111                 :            : static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
     112                 :            : static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
     113                 :            : static rtx expand_builtin_interclass_mathfn (tree, rtx);
     114                 :            : static rtx expand_builtin_sincos (tree);
     115                 :            : static rtx expand_builtin_cexpi (tree, rtx);
     116                 :            : static rtx expand_builtin_int_roundingfn (tree, rtx);
     117                 :            : static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
     118                 :            : static rtx expand_builtin_next_arg (void);
     119                 :            : static rtx expand_builtin_va_start (tree);
     120                 :            : static rtx expand_builtin_va_end (tree);
     121                 :            : static rtx expand_builtin_va_copy (tree);
     122                 :            : static rtx inline_expand_builtin_string_cmp (tree, rtx);
     123                 :            : static rtx expand_builtin_strcmp (tree, rtx);
     124                 :            : static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
     125                 :            : static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
     126                 :            : static rtx expand_builtin_memchr (tree, rtx);
     127                 :            : static rtx expand_builtin_memcpy (tree, rtx);
     128                 :            : static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
     129                 :            :                                             rtx target, tree exp,
     130                 :            :                                             memop_ret retmode,
     131                 :            :                                             bool might_overlap);
     132                 :            : static rtx expand_builtin_memmove (tree, rtx);
     133                 :            : static rtx expand_builtin_mempcpy (tree, rtx);
     134                 :            : static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
     135                 :            : static rtx expand_builtin_strcat (tree);
     136                 :            : static rtx expand_builtin_strcpy (tree, rtx);
     137                 :            : static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
     138                 :            : static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
     139                 :            : static rtx expand_builtin_stpncpy (tree, rtx);
     140                 :            : static rtx expand_builtin_strncat (tree, rtx);
     141                 :            : static rtx expand_builtin_strncpy (tree, rtx);
     142                 :            : static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, scalar_int_mode);
     143                 :            : static rtx expand_builtin_memset (tree, rtx, machine_mode);
     144                 :            : static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
     145                 :            : static rtx expand_builtin_bzero (tree);
     146                 :            : static rtx expand_builtin_strlen (tree, rtx, machine_mode);
     147                 :            : static rtx expand_builtin_strnlen (tree, rtx, machine_mode);
     148                 :            : static rtx expand_builtin_alloca (tree);
     149                 :            : static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
     150                 :            : static rtx expand_builtin_frame_address (tree, tree);
     151                 :            : static tree stabilize_va_list_loc (location_t, tree, int);
     152                 :            : static rtx expand_builtin_expect (tree, rtx);
     153                 :            : static rtx expand_builtin_expect_with_probability (tree, rtx);
     154                 :            : static tree fold_builtin_constant_p (tree);
     155                 :            : static tree fold_builtin_classify_type (tree);
     156                 :            : static tree fold_builtin_strlen (location_t, tree, tree);
     157                 :            : static tree fold_builtin_inf (location_t, tree, int);
     158                 :            : static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
     159                 :            : static bool validate_arg (const_tree, enum tree_code code);
     160                 :            : static rtx expand_builtin_fabs (tree, rtx, rtx);
     161                 :            : static rtx expand_builtin_signbit (tree, rtx);
     162                 :            : static tree fold_builtin_memcmp (location_t, tree, tree, tree);
     163                 :            : static tree fold_builtin_isascii (location_t, tree);
     164                 :            : static tree fold_builtin_toascii (location_t, tree);
     165                 :            : static tree fold_builtin_isdigit (location_t, tree);
     166                 :            : static tree fold_builtin_fabs (location_t, tree, tree);
     167                 :            : static tree fold_builtin_abs (location_t, tree, tree);
     168                 :            : static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
     169                 :            :                                         enum tree_code);
     170                 :            : static tree fold_builtin_varargs (location_t, tree, tree*, int);
     171                 :            : 
     172                 :            : static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
     173                 :            : static tree fold_builtin_strspn (location_t, tree, tree, tree);
     174                 :            : static tree fold_builtin_strcspn (location_t, tree, tree, tree);
     175                 :            : 
     176                 :            : static rtx expand_builtin_object_size (tree);
     177                 :            : static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
     178                 :            :                                       enum built_in_function);
     179                 :            : static void maybe_emit_chk_warning (tree, enum built_in_function);
     180                 :            : static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
     181                 :            : static void maybe_emit_free_warning (tree);
     182                 :            : static tree fold_builtin_object_size (tree, tree);
     183                 :            : 
     184                 :            : unsigned HOST_WIDE_INT target_newline;
     185                 :            : unsigned HOST_WIDE_INT target_percent;
     186                 :            : static unsigned HOST_WIDE_INT target_c;
     187                 :            : static unsigned HOST_WIDE_INT target_s;
     188                 :            : char target_percent_c[3];
     189                 :            : char target_percent_s[3];
     190                 :            : char target_percent_s_newline[4];
     191                 :            : static tree do_mpfr_remquo (tree, tree, tree);
     192                 :            : static tree do_mpfr_lgamma_r (tree, tree, tree);
     193                 :            : static void expand_builtin_sync_synchronize (void);
     194                 :            : 
     195                 :            : /* Return true if NAME starts with __builtin_ or __sync_.  */
     196                 :            : 
     197                 :            : static bool
     198                 :     334811 : is_builtin_name (const char *name)
     199                 :            : {
     200                 :     334811 :   if (strncmp (name, "__builtin_", 10) == 0)
     201                 :            :     return true;
     202                 :     123382 :   if (strncmp (name, "__sync_", 7) == 0)
     203                 :            :     return true;
     204                 :     122117 :   if (strncmp (name, "__atomic_", 9) == 0)
     205                 :      24196 :     return true;
     206                 :            :   return false;
     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                 :     334811 : 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                 :     334811 :   const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
     220                 :     334811 :   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                 :            : static bool
     239                 :   37604700 : get_object_alignment_2 (tree exp, unsigned int *alignp,
     240                 :            :                         unsigned HOST_WIDE_INT *bitposp, bool addr_p)
     241                 :            : {
     242                 :   37604700 :   poly_int64 bitsize, bitpos;
     243                 :   37604700 :   tree offset;
     244                 :   37604700 :   machine_mode mode;
     245                 :   37604700 :   int unsignedp, reversep, volatilep;
     246                 :   37604700 :   unsigned int align = BITS_PER_UNIT;
     247                 :   37604700 :   bool known_alignment = false;
     248                 :            : 
     249                 :            :   /* Get the innermost object and the constant (bitpos) and possibly
     250                 :            :      variable (offset) offset of the access.  */
     251                 :   37604700 :   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                 :   37604700 :   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                 :   37439900 :   else if (TREE_CODE (exp) == LABEL_DECL)
     266                 :            :     ;
     267                 :   37419800 :   else if (TREE_CODE (exp) == CONST_DECL)
     268                 :            :     {
     269                 :            :       /* The alignment of a CONST_DECL is determined by its initializer.  */
     270                 :      27192 :       exp = DECL_INITIAL (exp);
     271                 :      27192 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     272                 :      27192 :       if (CONSTANT_CLASS_P (exp))
     273                 :      27192 :         align = targetm.constant_alignment (exp, align);
     274                 :            : 
     275                 :            :       known_alignment = true;
     276                 :            :     }
     277                 :   37392600 :   else if (DECL_P (exp))
     278                 :            :     {
     279                 :   20829900 :       align = DECL_ALIGN (exp);
     280                 :            :       known_alignment = true;
     281                 :            :     }
     282                 :   16562700 :   else if (TREE_CODE (exp) == INDIRECT_REF
     283                 :   16558400 :            || TREE_CODE (exp) == MEM_REF
     284                 :    2708290 :            || TREE_CODE (exp) == TARGET_MEM_REF)
     285                 :            :     {
     286                 :   15053600 :       tree addr = TREE_OPERAND (exp, 0);
     287                 :   15053600 :       unsigned ptr_align;
     288                 :   15053600 :       unsigned HOST_WIDE_INT ptr_bitpos;
     289                 :   15053600 :       unsigned HOST_WIDE_INT ptr_bitmask = ~0;
     290                 :            : 
     291                 :            :       /* If the address is explicitely aligned, handle that.  */
     292                 :   15053600 :       if (TREE_CODE (addr) == BIT_AND_EXPR
     293                 :   15053600 :           && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
     294                 :            :         {
     295                 :         80 :           ptr_bitmask = TREE_INT_CST_LOW (TREE_OPERAND (addr, 1));
     296                 :         80 :           ptr_bitmask *= BITS_PER_UNIT;
     297                 :         80 :           align = least_bit_hwi (ptr_bitmask);
     298                 :         80 :           addr = TREE_OPERAND (addr, 0);
     299                 :            :         }
     300                 :            : 
     301                 :   15053600 :       known_alignment
     302                 :   15053600 :         = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
     303                 :   15053600 :       align = MAX (ptr_align, align);
     304                 :            : 
     305                 :            :       /* Re-apply explicit alignment to the bitpos.  */
     306                 :   15053600 :       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                 :   15053600 :       if (TREE_CODE (exp) == TARGET_MEM_REF)
     311                 :            :         {
     312                 :    1199180 :           if (TMR_INDEX (exp))
     313                 :            :             {
     314                 :     603147 :               unsigned HOST_WIDE_INT step = 1;
     315                 :     603147 :               if (TMR_STEP (exp))
     316                 :     310256 :                 step = TREE_INT_CST_LOW (TMR_STEP (exp));
     317                 :     603147 :               align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
     318                 :            :             }
     319                 :    1199180 :           if (TMR_INDEX2 (exp))
     320                 :      11448 :             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                 :   15053600 :       unsigned int talign;
     330                 :   15053600 :       if (!addr_p && !known_alignment
     331                 :   13669500 :           && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
     332                 :   28722400 :           && talign > align)
     333                 :            :         align = talign;
     334                 :            :       else
     335                 :            :         {
     336                 :            :           /* Else adjust bitpos accordingly.  */
     337                 :    3246800 :           bitpos += ptr_bitpos;
     338                 :    3246800 :           if (TREE_CODE (exp) == MEM_REF
     339                 :    3246800 :               || TREE_CODE (exp) == TARGET_MEM_REF)
     340                 :    3244190 :             bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
     341                 :   15053600 :         }
     342                 :            :     }
     343                 :    1509110 :   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                 :    1482180 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     348                 :    1482180 :       if (CONSTANT_CLASS_P (exp))
     349                 :    1482180 :         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                 :   37604700 :   if (offset)
     357                 :            :     {
     358                 :     897470 :       unsigned int trailing_zeros = tree_ctz (offset);
     359                 :     897470 :       if (trailing_zeros < HOST_BITS_PER_INT)
     360                 :            :         {
     361                 :     897403 :           unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     362                 :     897403 :           if (inner)
     363                 :     897403 :             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                 :   37604700 :   unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
     370                 :   37604700 :   if (alt_align != 0 && alt_align < align)
     371                 :            :     {
     372                 :            :       align = alt_align;
     373                 :            :       known_alignment = false;
     374                 :            :     }
     375                 :            : 
     376                 :   37604700 :   *alignp = align;
     377                 :   37604700 :   *bitposp = bitpos.coeffs[0] & (align - 1);
     378                 :   37604700 :   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                 :   32353000 : get_object_alignment_1 (tree exp, unsigned int *alignp,
     388                 :            :                         unsigned HOST_WIDE_INT *bitposp)
     389                 :            : {
     390                 :   32353000 :   return get_object_alignment_2 (exp, alignp, bitposp, false);
     391                 :            : }
     392                 :            : 
     393                 :            : /* Return the alignment in bits of EXP, an object.  */
     394                 :            : 
     395                 :            : unsigned int
     396                 :    7391750 : get_object_alignment (tree exp)
     397                 :            : {
     398                 :    7391750 :   unsigned HOST_WIDE_INT bitpos = 0;
     399                 :    7391750 :   unsigned int align;
     400                 :            : 
     401                 :    7391750 :   get_object_alignment_1 (exp, &align, &bitpos);
     402                 :            : 
     403                 :            :   /* align and bitpos now specify known low bits of the pointer.
     404                 :            :      ptr & (align - 1) == bitpos.  */
     405                 :            : 
     406                 :    7391750 :   if (bitpos != 0)
     407                 :     126030 :     align = least_bit_hwi (bitpos);
     408                 :    7391750 :   return align;
     409                 :            : }
     410                 :            : 
     411                 :            : /* For a pointer valued expression EXP compute values M and N such that M
     412                 :            :    divides (EXP - N) and such that N < M.  If these numbers can be determined,
     413                 :            :    store M in alignp and N in *BITPOSP and return true.  Return false if
     414                 :            :    the results are just a conservative approximation.
     415                 :            : 
     416                 :            :    If EXP is not a pointer, false is returned too.  */
     417                 :            : 
     418                 :            : bool
     419                 :   27436300 : get_pointer_alignment_1 (tree exp, unsigned int *alignp,
     420                 :            :                          unsigned HOST_WIDE_INT *bitposp)
     421                 :            : {
     422                 :   27436300 :   STRIP_NOPS (exp);
     423                 :            : 
     424                 :   27436300 :   if (TREE_CODE (exp) == ADDR_EXPR)
     425                 :    5251660 :     return get_object_alignment_2 (TREE_OPERAND (exp, 0),
     426                 :    5251660 :                                    alignp, bitposp, true);
     427                 :   22184600 :   else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
     428                 :            :     {
     429                 :     240345 :       unsigned int align;
     430                 :     240345 :       unsigned HOST_WIDE_INT bitpos;
     431                 :     240345 :       bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
     432                 :            :                                           &align, &bitpos);
     433                 :     240345 :       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
     434                 :        929 :         bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
     435                 :            :       else
     436                 :            :         {
     437                 :     239416 :           unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
     438                 :     239416 :           if (trailing_zeros < HOST_BITS_PER_INT)
     439                 :            :             {
     440                 :     239416 :               unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     441                 :     239416 :               if (inner)
     442                 :     239416 :                 align = MIN (align, inner);
     443                 :            :             }
     444                 :            :         }
     445                 :     240345 :       *alignp = align;
     446                 :     240345 :       *bitposp = bitpos & (align - 1);
     447                 :     240345 :       return res;
     448                 :            :     }
     449                 :   21944300 :   else if (TREE_CODE (exp) == SSA_NAME
     450                 :   42831500 :            && POINTER_TYPE_P (TREE_TYPE (exp)))
     451                 :            :     {
     452                 :   20886700 :       unsigned int ptr_align, ptr_misalign;
     453                 :   20886700 :       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
     454                 :            : 
     455                 :   20886700 :       if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
     456                 :            :         {
     457                 :    1124540 :           *bitposp = ptr_misalign * BITS_PER_UNIT;
     458                 :    1124540 :           *alignp = ptr_align * BITS_PER_UNIT;
     459                 :            :           /* Make sure to return a sensible alignment when the multiplication
     460                 :            :              by BITS_PER_UNIT overflowed.  */
     461                 :    1124540 :           if (*alignp == 0)
     462                 :         30 :             *alignp = 1u << (HOST_BITS_PER_INT - 1);
     463                 :            :           /* We cannot really tell whether this result is an approximation.  */
     464                 :    1124540 :           return false;
     465                 :            :         }
     466                 :            :       else
     467                 :            :         {
     468                 :   19762200 :           *bitposp = 0;
     469                 :   19762200 :           *alignp = BITS_PER_UNIT;
     470                 :   19762200 :           return false;
     471                 :            :         }
     472                 :            :     }
     473                 :    1057550 :   else if (TREE_CODE (exp) == INTEGER_CST)
     474                 :            :     {
     475                 :      23711 :       *alignp = BIGGEST_ALIGNMENT;
     476                 :      23711 :       *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
     477                 :      23711 :                   & (BIGGEST_ALIGNMENT - 1));
     478                 :      23711 :       return true;
     479                 :            :     }
     480                 :            : 
     481                 :    1033840 :   *bitposp = 0;
     482                 :    1033840 :   *alignp = BITS_PER_UNIT;
     483                 :    1033840 :   return false;
     484                 :            : }
     485                 :            : 
     486                 :            : /* Return the alignment in bits of EXP, a pointer valued expression.
     487                 :            :    The alignment returned is, by default, the alignment of the thing that
     488                 :            :    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
     489                 :            : 
     490                 :            :    Otherwise, look at the expression to see if we can do better, i.e., if the
     491                 :            :    expression is actually pointing at an object whose alignment is tighter.  */
     492                 :            : 
     493                 :            : unsigned int
     494                 :    6606440 : get_pointer_alignment (tree exp)
     495                 :            : {
     496                 :    6606440 :   unsigned HOST_WIDE_INT bitpos = 0;
     497                 :    6606440 :   unsigned int align;
     498                 :            : 
     499                 :    6606440 :   get_pointer_alignment_1 (exp, &align, &bitpos);
     500                 :            : 
     501                 :            :   /* align and bitpos now specify known low bits of the pointer.
     502                 :            :      ptr & (align - 1) == bitpos.  */
     503                 :            : 
     504                 :    6606440 :   if (bitpos != 0)
     505                 :      40197 :     align = least_bit_hwi (bitpos);
     506                 :            : 
     507                 :    6606440 :   return align;
     508                 :            : }
     509                 :            : 
     510                 :            : /* Return the number of leading non-zero elements in the sequence
     511                 :            :    [ PTR, PTR + MAXELTS ) where each element's size is ELTSIZE bytes.
     512                 :            :    ELTSIZE must be a power of 2 less than 8.  Used by c_strlen.  */
     513                 :            : 
     514                 :            : unsigned
     515                 :     181102 : string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
     516                 :            : {
     517                 :     181102 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     518                 :            : 
     519                 :     181102 :   unsigned n;
     520                 :            : 
     521                 :     181102 :   if (eltsize == 1)
     522                 :            :     {
     523                 :            :       /* Optimize the common case of plain char.  */
     524                 :  121299000 :       for (n = 0; n < maxelts; n++)
     525                 :            :         {
     526                 :  121214000 :           const char *elt = (const char*) ptr + n;
     527                 :  121214000 :           if (!*elt)
     528                 :            :             break;
     529                 :            :         }
     530                 :            :     }
     531                 :            :   else
     532                 :            :     {
     533                 :        590 :       for (n = 0; n < maxelts; n++)
     534                 :            :         {
     535                 :        566 :           const char *elt = (const char*) ptr + n * eltsize;
     536                 :        566 :           if (!memcmp (elt, "\0\0\0\0", eltsize))
     537                 :            :             break;
     538                 :            :         }
     539                 :            :     }
     540                 :     181102 :   return n;
     541                 :            : }
     542                 :            : 
     543                 :            : /* For a call at LOC to a function FN that expects a string in the argument
     544                 :            :    ARG, issue a diagnostic due to it being a called with an argument
     545                 :            :    declared at NONSTR that is a character array with no terminating NUL.  */
     546                 :            : 
     547                 :            : void
     548                 :      17487 : warn_string_no_nul (location_t loc, const char *fn, tree arg, tree decl)
     549                 :            : {
     550                 :      17487 :   if (TREE_NO_WARNING (arg))
     551                 :            :     return;
     552                 :            : 
     553                 :      16188 :   loc = expansion_point_location_if_in_system_header (loc);
     554                 :            : 
     555                 :      16188 :   if (warning_at (loc, OPT_Wstringop_overflow_,
     556                 :            :                   "%qs argument missing terminating nul", fn))
     557                 :            :     {
     558                 :        401 :       inform (DECL_SOURCE_LOCATION (decl),
     559                 :            :               "referenced argument declared here");
     560                 :        401 :       TREE_NO_WARNING (arg) = 1;
     561                 :            :     }
     562                 :            : }
     563                 :            : 
     564                 :            : /* For a call EXPR (which may be null) that expects a string argument
     565                 :            :    and SRC as the argument, returns false if SRC is a character array
     566                 :            :    with no terminating NUL.  When nonnull, BOUND is the number of
     567                 :            :    characters in which to expect the terminating NUL.
     568                 :            :    When EXPR is nonnull also issues a warning.  */
     569                 :            : 
     570                 :            : bool
     571                 :      46306 : check_nul_terminated_array (tree expr, tree src, tree bound /* = NULL_TREE */)
     572                 :            : {
     573                 :      46306 :   tree size;
     574                 :      46306 :   bool exact;
     575                 :      46306 :   tree nonstr = unterminated_array (src, &size, &exact);
     576                 :      46306 :   if (!nonstr)
     577                 :            :     return true;
     578                 :            : 
     579                 :            :   /* NONSTR refers to the non-nul terminated constant array and SIZE
     580                 :            :      is the constant size of the array in bytes.  EXACT is true when
     581                 :            :      SIZE is exact.  */
     582                 :            : 
     583                 :        359 :   if (bound)
     584                 :            :     {
     585                 :         51 :       wide_int min, max;
     586                 :         51 :       if (TREE_CODE (bound) == INTEGER_CST)
     587                 :         41 :         min = max = wi::to_wide (bound);
     588                 :            :       else
     589                 :            :         {
     590                 :         10 :           value_range_kind rng = get_range_info (bound, &min, &max);
     591                 :         10 :           if (rng != VR_RANGE)
     592                 :         31 :             return true;
     593                 :            :         }
     594                 :            : 
     595                 :         41 :       if (wi::leu_p (min, wi::to_wide (size)))
     596                 :            :         return true;
     597                 :            :     }
     598                 :            : 
     599                 :        328 :   if (expr && !TREE_NO_WARNING (expr))
     600                 :            :     {
     601                 :         90 :       tree fndecl = get_callee_fndecl (expr);
     602                 :         90 :       const char *fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
     603                 :         90 :       warn_string_no_nul (EXPR_LOCATION (expr), fname, src, nonstr);
     604                 :            :     }
     605                 :            : 
     606                 :            :   return false;
     607                 :            : }
     608                 :            : 
     609                 :            : /* If EXP refers to an unterminated constant character array return
     610                 :            :    the declaration of the object of which the array is a member or
     611                 :            :    element and if SIZE is not null, set *SIZE to the size of
     612                 :            :    the unterminated array and set *EXACT if the size is exact or
     613                 :            :    clear it otherwise.  Otherwise return null.  */
     614                 :            : 
     615                 :            : tree
     616                 :      51257 : unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */)
     617                 :            : {
     618                 :            :   /* C_STRLEN will return NULL and set DECL in the info
     619                 :            :      structure if EXP references a unterminated array.  */
     620                 :      51257 :   c_strlen_data lendata = { };
     621                 :      51257 :   tree len = c_strlen (exp, 1, &lendata);
     622                 :      51257 :   if (len == NULL_TREE && lendata.minlen && lendata.decl)
     623                 :            :      {
     624                 :       1244 :        if (size)
     625                 :            :         {
     626                 :        501 :           len = lendata.minlen;
     627                 :        501 :           if (lendata.off)
     628                 :            :             {
     629                 :            :               /* Constant offsets are already accounted for in LENDATA.MINLEN,
     630                 :            :                  but not in a SSA_NAME + CST expression.  */
     631                 :        501 :               if (TREE_CODE (lendata.off) == INTEGER_CST)
     632                 :        458 :                 *exact = true;
     633                 :         43 :               else if (TREE_CODE (lendata.off) == PLUS_EXPR
     634                 :         43 :                        && TREE_CODE (TREE_OPERAND (lendata.off, 1)) == INTEGER_CST)
     635                 :            :                 {
     636                 :            :                   /* Subtract the offset from the size of the array.  */
     637                 :         14 :                   *exact = false;
     638                 :         14 :                   tree temp = TREE_OPERAND (lendata.off, 1);
     639                 :         14 :                   temp = fold_convert (ssizetype, temp);
     640                 :         14 :                   len = fold_build2 (MINUS_EXPR, ssizetype, len, temp);
     641                 :            :                 }
     642                 :            :               else
     643                 :         29 :                 *exact = false;
     644                 :            :             }
     645                 :            :           else
     646                 :          0 :             *exact = true;
     647                 :            : 
     648                 :        501 :           *size = len;
     649                 :            :         }
     650                 :       1244 :        return lendata.decl;
     651                 :            :      }
     652                 :            : 
     653                 :            :   return NULL_TREE;
     654                 :            : }
     655                 :            : 
     656                 :            : /* Compute the length of a null-terminated character string or wide
     657                 :            :    character string handling character sizes of 1, 2, and 4 bytes.
     658                 :            :    TREE_STRING_LENGTH is not the right way because it evaluates to
     659                 :            :    the size of the character array in bytes (as opposed to characters)
     660                 :            :    and because it can contain a zero byte in the middle.
     661                 :            : 
     662                 :            :    ONLY_VALUE should be nonzero if the result is not going to be emitted
     663                 :            :    into the instruction stream and zero if it is going to be expanded.
     664                 :            :    E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
     665                 :            :    is returned, otherwise NULL, since
     666                 :            :    len = c_strlen (ARG, 1); if (len) expand_expr (len, ...); would not
     667                 :            :    evaluate the side-effects.
     668                 :            : 
     669                 :            :    If ONLY_VALUE is two then we do not emit warnings about out-of-bound
     670                 :            :    accesses.  Note that this implies the result is not going to be emitted
     671                 :            :    into the instruction stream.
     672                 :            : 
     673                 :            :    Additional information about the string accessed may be recorded
     674                 :            :    in DATA.  For example, if ARG references an unterminated string,
     675                 :            :    then the declaration will be stored in the DECL field.   If the
     676                 :            :    length of the unterminated string can be determined, it'll be
     677                 :            :    stored in the LEN field.  Note this length could well be different
     678                 :            :    than what a C strlen call would return.
     679                 :            : 
     680                 :            :    ELTSIZE is 1 for normal single byte character strings, and 2 or
     681                 :            :    4 for wide characer strings.  ELTSIZE is by default 1.
     682                 :            : 
     683                 :            :    The value returned is of type `ssizetype'.  */
     684                 :            : 
     685                 :            : tree
     686                 :    1012560 : c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
     687                 :            : {
     688                 :            :   /* If we were not passed a DATA pointer, then get one to a local
     689                 :            :      structure.  That avoids having to check DATA for NULL before
     690                 :            :      each time we want to use it.  */
     691                 :    1012560 :   c_strlen_data local_strlen_data = { };
     692                 :    1012560 :   if (!data)
     693                 :     200884 :     data = &local_strlen_data;
     694                 :            : 
     695                 :    1012560 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     696                 :            : 
     697                 :    1012560 :   tree src = STRIP_NOPS (arg);
     698                 :    1012560 :   if (TREE_CODE (src) == COND_EXPR
     699                 :    1012560 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     700                 :            :     {
     701                 :        698 :       tree len1, len2;
     702                 :            : 
     703                 :        698 :       len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     704                 :        698 :       len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
     705                 :        698 :       if (tree_int_cst_equal (len1, len2))
     706                 :            :         return len1;
     707                 :            :     }
     708                 :            : 
     709                 :    1012400 :   if (TREE_CODE (src) == COMPOUND_EXPR
     710                 :    1012400 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     711                 :         45 :     return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     712                 :            : 
     713                 :    1012350 :   location_t loc = EXPR_LOC_OR_LOC (src, input_location);
     714                 :            : 
     715                 :            :   /* Offset from the beginning of the string in bytes.  */
     716                 :    1012350 :   tree byteoff;
     717                 :    1012350 :   tree memsize;
     718                 :    1012350 :   tree decl;
     719                 :    1012350 :   src = string_constant (src, &byteoff, &memsize, &decl);
     720                 :    1012350 :   if (src == 0)
     721                 :            :     return NULL_TREE;
     722                 :            : 
     723                 :            :   /* Determine the size of the string element.  */
     724                 :     189796 :   if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
     725                 :            :     return NULL_TREE;
     726                 :            : 
     727                 :            :   /* Set MAXELTS to sizeof (SRC) / sizeof (*SRC) - 1, the maximum possible
     728                 :            :      length of SRC.  Prefer TYPE_SIZE() to TREE_STRING_LENGTH() if possible
     729                 :            :      in case the latter is less than the size of the array, such as when
     730                 :            :      SRC refers to a short string literal used to initialize a large array.
     731                 :            :      In that case, the elements of the array after the terminating NUL are
     732                 :            :      all NUL.  */
     733                 :     183703 :   HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
     734                 :     183703 :   strelts = strelts / eltsize;
     735                 :            : 
     736                 :     183703 :   if (!tree_fits_uhwi_p (memsize))
     737                 :            :     return NULL_TREE;
     738                 :            : 
     739                 :     183703 :   HOST_WIDE_INT maxelts = tree_to_uhwi (memsize) / eltsize;
     740                 :            : 
     741                 :            :   /* PTR can point to the byte representation of any string type, including
     742                 :            :      char* and wchar_t*.  */
     743                 :     183703 :   const char *ptr = TREE_STRING_POINTER (src);
     744                 :            : 
     745                 :     183703 :   if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
     746                 :            :     {
     747                 :            :       /* The code below works only for single byte character types.  */
     748                 :       3396 :       if (eltsize != 1)
     749                 :            :         return NULL_TREE;
     750                 :            : 
     751                 :            :       /* If the string has an internal NUL character followed by any
     752                 :            :          non-NUL characters (e.g., "foo\0bar"), we can't compute
     753                 :            :          the offset to the following NUL if we don't know where to
     754                 :            :          start searching for it.  */
     755                 :       3396 :       unsigned len = string_length (ptr, eltsize, strelts);
     756                 :            : 
     757                 :            :       /* Return when an embedded null character is found or none at all.
     758                 :            :          In the latter case, set the DECL/LEN field in the DATA structure
     759                 :            :          so that callers may examine them.  */
     760                 :       3396 :       if (len + 1 < strelts)
     761                 :            :         return NULL_TREE;
     762                 :       2551 :       else if (len >= maxelts)
     763                 :            :         {
     764                 :       1018 :           data->decl = decl;
     765                 :       1018 :           data->off = byteoff;
     766                 :       1018 :           data->minlen = ssize_int (len);
     767                 :       1018 :           return NULL_TREE;
     768                 :            :         }
     769                 :            : 
     770                 :            :       /* For empty strings the result should be zero.  */
     771                 :       1533 :       if (len == 0)
     772                 :         27 :         return ssize_int (0);
     773                 :            : 
     774                 :            :       /* We don't know the starting offset, but we do know that the string
     775                 :            :          has no internal zero bytes.  If the offset falls within the bounds
     776                 :            :          of the string subtract the offset from the length of the string,
     777                 :            :          and return that.  Otherwise the length is zero.  Take care to
     778                 :            :          use SAVE_EXPR in case the OFFSET has side-effects.  */
     779                 :       1778 :       tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
     780                 :       1506 :                                                  : byteoff;
     781                 :       1506 :       offsave = fold_convert_loc (loc, sizetype, offsave);
     782                 :       1506 :       tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
     783                 :            :                                       size_int (len));
     784                 :       1506 :       tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
     785                 :            :                                      offsave);
     786                 :       1506 :       lenexp = fold_convert_loc (loc, ssizetype, lenexp);
     787                 :       1506 :       return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
     788                 :       1506 :                               build_zero_cst (ssizetype));
     789                 :            :     }
     790                 :            : 
     791                 :            :   /* Offset from the beginning of the string in elements.  */
     792                 :     180307 :   HOST_WIDE_INT eltoff;
     793                 :            : 
     794                 :            :   /* We have a known offset into the string.  Start searching there for
     795                 :            :      a null character if we can represent it as a single HOST_WIDE_INT.  */
     796                 :     180307 :   if (byteoff == 0)
     797                 :            :     eltoff = 0;
     798                 :     180307 :   else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
     799                 :            :     eltoff = -1;
     800                 :            :   else
     801                 :     179389 :     eltoff = tree_to_uhwi (byteoff) / eltsize;
     802                 :            : 
     803                 :            :   /* If the offset is known to be out of bounds, warn, and call strlen at
     804                 :            :      runtime.  */
     805                 :     180307 :   if (eltoff < 0 || eltoff >= maxelts)
     806                 :            :     {
     807                 :            :       /* Suppress multiple warnings for propagated constant strings.  */
     808                 :       2601 :       if (only_value != 2
     809                 :       2601 :           && !TREE_NO_WARNING (arg)
     810                 :       3244 :           && warning_at (loc, OPT_Warray_bounds,
     811                 :            :                          "offset %qwi outside bounds of constant string",
     812                 :            :                          eltoff))
     813                 :            :         {
     814                 :        643 :           if (decl)
     815                 :        642 :             inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
     816                 :        643 :           TREE_NO_WARNING (arg) = 1;
     817                 :            :         }
     818                 :       2601 :       return NULL_TREE;
     819                 :            :     }
     820                 :            : 
     821                 :            :   /* If eltoff is larger than strelts but less than maxelts the
     822                 :            :      string length is zero, since the excess memory will be zero.  */
     823                 :     177706 :   if (eltoff > strelts)
     824                 :          0 :     return ssize_int (0);
     825                 :            : 
     826                 :            :   /* Use strlen to search for the first zero byte.  Since any strings
     827                 :            :      constructed with build_string will have nulls appended, we win even
     828                 :            :      if we get handed something like (char[4])"abcd".
     829                 :            : 
     830                 :            :      Since ELTOFF is our starting index into the string, no further
     831                 :            :      calculation is needed.  */
     832                 :     177706 :   unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
     833                 :     177706 :                                 strelts - eltoff);
     834                 :            : 
     835                 :            :   /* Don't know what to return if there was no zero termination.
     836                 :            :      Ideally this would turn into a gcc_checking_assert over time.
     837                 :            :      Set DECL/LEN so callers can examine them.  */
     838                 :     177706 :   if (len >= maxelts - eltoff)
     839                 :            :     {
     840                 :      79811 :       data->decl = decl;
     841                 :      79811 :       data->off = byteoff;
     842                 :      79811 :       data->minlen = ssize_int (len);
     843                 :      79811 :       return NULL_TREE;
     844                 :            :     }
     845                 :            : 
     846                 :      97895 :   return ssize_int (len);
     847                 :            : }
     848                 :            : 
     849                 :            : /* Return a constant integer corresponding to target reading
     850                 :            :    GET_MODE_BITSIZE (MODE) bits from string constant STR.  If
     851                 :            :    NULL_TERMINATED_P, reading stops after '\0' character, all further ones
     852                 :            :    are assumed to be zero, otherwise it reads as many characters
     853                 :            :    as needed.  */
     854                 :            : 
     855                 :            : rtx
     856                 :     137578 : c_readstr (const char *str, scalar_int_mode mode,
     857                 :            :            bool null_terminated_p/*=true*/)
     858                 :            : {
     859                 :     137578 :   HOST_WIDE_INT ch;
     860                 :     137578 :   unsigned int i, j;
     861                 :     137578 :   HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
     862                 :            : 
     863                 :     137578 :   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
     864                 :     137578 :   unsigned int len = (GET_MODE_PRECISION (mode) + HOST_BITS_PER_WIDE_INT - 1)
     865                 :     137578 :     / HOST_BITS_PER_WIDE_INT;
     866                 :            : 
     867                 :     137578 :   gcc_assert (len <= MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT);
     868                 :     319900 :   for (i = 0; i < len; i++)
     869                 :     182322 :     tmp[i] = 0;
     870                 :            : 
     871                 :            :   ch = 1;
     872                 :    2359500 :   for (i = 0; i < GET_MODE_SIZE (mode); i++)
     873                 :            :     {
     874                 :    1042170 :       j = i;
     875                 :    1042170 :       if (WORDS_BIG_ENDIAN)
     876                 :            :         j = GET_MODE_SIZE (mode) - i - 1;
     877                 :    1042170 :       if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
     878                 :            :           && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
     879                 :            :         j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
     880                 :    1042170 :       j *= BITS_PER_UNIT;
     881                 :            : 
     882                 :    1042170 :       if (ch || !null_terminated_p)
     883                 :    1041680 :         ch = (unsigned char) str[i];
     884                 :    1042170 :       tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
     885                 :            :     }
     886                 :            : 
     887                 :     137578 :   wide_int c = wide_int::from_array (tmp, len, GET_MODE_PRECISION (mode));
     888                 :     137578 :   return immed_wide_int_const (c, mode);
     889                 :            : }
     890                 :            : 
     891                 :            : /* Cast a target constant CST to target CHAR and if that value fits into
     892                 :            :    host char type, return zero and put that value into variable pointed to by
     893                 :            :    P.  */
     894                 :            : 
     895                 :            : static int
     896                 :      22545 : target_char_cast (tree cst, char *p)
     897                 :            : {
     898                 :      22545 :   unsigned HOST_WIDE_INT val, hostval;
     899                 :            : 
     900                 :          0 :   if (TREE_CODE (cst) != INTEGER_CST
     901                 :            :       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
     902                 :            :     return 1;
     903                 :            : 
     904                 :            :   /* Do not care if it fits or not right here.  */
     905                 :          0 :   val = TREE_INT_CST_LOW (cst);
     906                 :            : 
     907                 :      22545 :   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
     908                 :      22545 :     val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
     909                 :            : 
     910                 :      22545 :   hostval = val;
     911                 :      22545 :   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
     912                 :      22545 :     hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
     913                 :            : 
     914                 :      22545 :   if (val != hostval)
     915                 :            :     return 1;
     916                 :            : 
     917                 :      22545 :   *p = hostval;
     918                 :          0 :   return 0;
     919                 :            : }
     920                 :            : 
     921                 :            : /* Similar to save_expr, but assumes that arbitrary code is not executed
     922                 :            :    in between the multiple evaluations.  In particular, we assume that a
     923                 :            :    non-addressable local variable will not be modified.  */
     924                 :            : 
     925                 :            : static tree
     926                 :      89155 : builtin_save_expr (tree exp)
     927                 :            : {
     928                 :      89155 :   if (TREE_CODE (exp) == SSA_NAME
     929                 :      62907 :       || (TREE_ADDRESSABLE (exp) == 0
     930                 :      62679 :           && (TREE_CODE (exp) == PARM_DECL
     931                 :      56016 :               || (VAR_P (exp) && !TREE_STATIC (exp)))))
     932                 :            :     return exp;
     933                 :            : 
     934                 :      55663 :   return save_expr (exp);
     935                 :            : }
     936                 :            : 
     937                 :            : /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
     938                 :            :    times to get the address of either a higher stack frame, or a return
     939                 :            :    address located within it (depending on FNDECL_CODE).  */
     940                 :            : 
     941                 :            : static rtx
     942                 :      14219 : expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
     943                 :            : {
     944                 :      14219 :   int i;
     945                 :      14219 :   rtx tem = INITIAL_FRAME_ADDRESS_RTX;
     946                 :      14219 :   if (tem == NULL_RTX)
     947                 :            :     {
     948                 :            :       /* For a zero count with __builtin_return_address, we don't care what
     949                 :            :          frame address we return, because target-specific definitions will
     950                 :            :          override us.  Therefore frame pointer elimination is OK, and using
     951                 :            :          the soft frame pointer is OK.
     952                 :            : 
     953                 :            :          For a nonzero count, or a zero count with __builtin_frame_address,
     954                 :            :          we require a stable offset from the current frame pointer to the
     955                 :            :          previous one, so we must use the hard frame pointer, and
     956                 :            :          we must disable frame pointer elimination.  */
     957                 :      14219 :       if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     958                 :       3852 :         tem = frame_pointer_rtx;
     959                 :            :       else
     960                 :            :         {
     961                 :      10367 :           tem = hard_frame_pointer_rtx;
     962                 :            : 
     963                 :            :           /* Tell reload not to eliminate the frame pointer.  */
     964                 :      10367 :           crtl->accesses_prior_frames = 1;
     965                 :            :         }
     966                 :            :     }
     967                 :            : 
     968                 :      14219 :   if (count > 0)
     969                 :        982 :     SETUP_FRAME_ADDRESSES ();
     970                 :            : 
     971                 :            :   /* On the SPARC, the return address is not in the frame, it is in a
     972                 :            :      register.  There is no way to access it off of the current frame
     973                 :            :      pointer, but it can be accessed off the previous frame pointer by
     974                 :            :      reading the value from the register window save area.  */
     975                 :            :   if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     976                 :            :     count--;
     977                 :            : 
     978                 :            :   /* Scan back COUNT frames to the specified frame.  */
     979                 :      50223 :   for (i = 0; i < count; i++)
     980                 :            :     {
     981                 :            :       /* Assume the dynamic chain pointer is in the word that the
     982                 :            :          frame address points to, unless otherwise specified.  */
     983                 :      36004 :       tem = DYNAMIC_CHAIN_ADDRESS (tem);
     984                 :      36004 :       tem = memory_address (Pmode, tem);
     985                 :      36004 :       tem = gen_frame_mem (Pmode, tem);
     986                 :      36004 :       tem = copy_to_reg (tem);
     987                 :            :     }
     988                 :            : 
     989                 :            :   /* For __builtin_frame_address, return what we've got.  But, on
     990                 :            :      the SPARC for example, we may have to add a bias.  */
     991                 :      14219 :   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
     992                 :            :     return FRAME_ADDR_RTX (tem);
     993                 :            : 
     994                 :            :   /* For __builtin_return_address, get the return address from that frame.  */
     995                 :            : #ifdef RETURN_ADDR_RTX
     996                 :       6892 :   tem = RETURN_ADDR_RTX (count, tem);
     997                 :            : #else
     998                 :            :   tem = memory_address (Pmode,
     999                 :            :                         plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
    1000                 :            :   tem = gen_frame_mem (Pmode, tem);
    1001                 :            : #endif
    1002                 :       4717 :   return tem;
    1003                 :            : }
    1004                 :            : 
    1005                 :            : /* Alias set used for setjmp buffer.  */
    1006                 :            : static alias_set_type setjmp_alias_set = -1;
    1007                 :            : 
    1008                 :            : /* Construct the leading half of a __builtin_setjmp call.  Control will
    1009                 :            :    return to RECEIVER_LABEL.  This is also called directly by the SJLJ
    1010                 :            :    exception handling code.  */
    1011                 :            : 
    1012                 :            : void
    1013                 :        786 : expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
    1014                 :            : {
    1015                 :        786 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
    1016                 :        786 :   rtx stack_save;
    1017                 :        786 :   rtx mem;
    1018                 :            : 
    1019                 :        786 :   if (setjmp_alias_set == -1)
    1020                 :        186 :     setjmp_alias_set = new_alias_set ();
    1021                 :            : 
    1022                 :       1572 :   buf_addr = convert_memory_address (Pmode, buf_addr);
    1023                 :            : 
    1024                 :        787 :   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
    1025                 :            : 
    1026                 :            :   /* We store the frame pointer and the address of receiver_label in
    1027                 :            :      the buffer and use the rest of it for the stack save area, which
    1028                 :            :      is machine-dependent.  */
    1029                 :            : 
    1030                 :        787 :   mem = gen_rtx_MEM (Pmode, buf_addr);
    1031                 :        786 :   set_mem_alias_set (mem, setjmp_alias_set);
    1032                 :        786 :   emit_move_insn (mem, hard_frame_pointer_rtx);
    1033                 :            : 
    1034                 :        787 :   mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
    1035                 :       1573 :                                            GET_MODE_SIZE (Pmode))),
    1036                 :        786 :   set_mem_alias_set (mem, setjmp_alias_set);
    1037                 :            : 
    1038                 :       1572 :   emit_move_insn (validize_mem (mem),
    1039                 :        788 :                   force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
    1040                 :            : 
    1041                 :        786 :   stack_save = gen_rtx_MEM (sa_mode,
    1042                 :        786 :                             plus_constant (Pmode, buf_addr,
    1043                 :       1573 :                                            2 * GET_MODE_SIZE (Pmode)));
    1044                 :        786 :   set_mem_alias_set (stack_save, setjmp_alias_set);
    1045                 :        786 :   emit_stack_save (SAVE_NONLOCAL, &stack_save);
    1046                 :            : 
    1047                 :            :   /* If there is further processing to do, do it.  */
    1048                 :        786 :   if (targetm.have_builtin_setjmp_setup ())
    1049                 :          0 :     emit_insn (targetm.gen_builtin_setjmp_setup (buf_addr));
    1050                 :            : 
    1051                 :            :   /* We have a nonlocal label.   */
    1052                 :        786 :   cfun->has_nonlocal_label = 1;
    1053                 :        786 : }
    1054                 :            : 
    1055                 :            : /* Construct the trailing part of a __builtin_setjmp call.  This is
    1056                 :            :    also called directly by the SJLJ exception handling code.
    1057                 :            :    If RECEIVER_LABEL is NULL, instead contruct a nonlocal goto handler.  */
    1058                 :            : 
    1059                 :            : void
    1060                 :       1289 : expand_builtin_setjmp_receiver (rtx receiver_label)
    1061                 :            : {
    1062                 :       1289 :   rtx chain;
    1063                 :            : 
    1064                 :            :   /* Mark the FP as used when we get here, so we have to make sure it's
    1065                 :            :      marked as used by this function.  */
    1066                 :       1289 :   emit_use (hard_frame_pointer_rtx);
    1067                 :            : 
    1068                 :            :   /* Mark the static chain as clobbered here so life information
    1069                 :            :      doesn't get messed up for it.  */
    1070                 :       1289 :   chain = rtx_for_static_chain (current_function_decl, true);
    1071                 :       1289 :   if (chain && REG_P (chain))
    1072                 :          0 :     emit_clobber (chain);
    1073                 :            : 
    1074                 :       1289 :   if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
    1075                 :            :     {
    1076                 :            :       /* If the argument pointer can be eliminated in favor of the
    1077                 :            :          frame pointer, we don't need to restore it.  We assume here
    1078                 :            :          that if such an elimination is present, it can always be used.
    1079                 :            :          This is the case on all known machines; if we don't make this
    1080                 :            :          assumption, we do unnecessary saving on many machines.  */
    1081                 :            :       size_t i;
    1082                 :            :       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
    1083                 :            : 
    1084                 :       2578 :       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
    1085                 :       2578 :         if (elim_regs[i].from == ARG_POINTER_REGNUM
    1086                 :       2578 :             && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
    1087                 :            :           break;
    1088                 :            : 
    1089                 :       1289 :       if (i == ARRAY_SIZE (elim_regs))
    1090                 :            :         {
    1091                 :            :           /* Now restore our arg pointer from the address at which it
    1092                 :            :              was saved in our stack frame.  */
    1093                 :          0 :           emit_move_insn (crtl->args.internal_arg_pointer,
    1094                 :            :                           copy_to_reg (get_arg_pointer_save_area ()));
    1095                 :            :         }
    1096                 :            :     }
    1097                 :            : 
    1098                 :       1289 :   if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
    1099                 :          0 :     emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
    1100                 :       1289 :   else if (targetm.have_nonlocal_goto_receiver ())
    1101                 :          0 :     emit_insn (targetm.gen_nonlocal_goto_receiver ());
    1102                 :            :   else
    1103                 :            :     { /* Nothing */ }
    1104                 :            : 
    1105                 :            :   /* We must not allow the code we just generated to be reordered by
    1106                 :            :      scheduling.  Specifically, the update of the frame pointer must
    1107                 :            :      happen immediately, not later.  */
    1108                 :       1289 :   emit_insn (gen_blockage ());
    1109                 :       1289 : }
    1110                 :            : 
    1111                 :            : /* __builtin_longjmp is passed a pointer to an array of five words (not
    1112                 :            :    all will be used on all machines).  It operates similarly to the C
    1113                 :            :    library function of the same name, but is more efficient.  Much of
    1114                 :            :    the code below is copied from the handling of non-local gotos.  */
    1115                 :            : 
    1116                 :            : static void
    1117                 :        355 : expand_builtin_longjmp (rtx buf_addr, rtx value)
    1118                 :            : {
    1119                 :        355 :   rtx fp, lab, stack;
    1120                 :        355 :   rtx_insn *insn, *last;
    1121                 :        355 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
    1122                 :            : 
    1123                 :            :   /* DRAP is needed for stack realign if longjmp is expanded to current
    1124                 :            :      function  */
    1125                 :        355 :   if (SUPPORTS_STACK_ALIGNMENT)
    1126                 :        355 :     crtl->need_drap = true;
    1127                 :            : 
    1128                 :        355 :   if (setjmp_alias_set == -1)
    1129                 :        324 :     setjmp_alias_set = new_alias_set ();
    1130                 :            : 
    1131                 :        710 :   buf_addr = convert_memory_address (Pmode, buf_addr);
    1132                 :            : 
    1133                 :        356 :   buf_addr = force_reg (Pmode, buf_addr);
    1134                 :            : 
    1135                 :            :   /* We require that the user must pass a second argument of 1, because
    1136                 :            :      that is what builtin_setjmp will return.  */
    1137                 :        355 :   gcc_assert (value == const1_rtx);
    1138                 :            : 
    1139                 :        355 :   last = get_last_insn ();
    1140                 :        355 :   if (targetm.have_builtin_longjmp ())
    1141                 :          0 :     emit_insn (targetm.gen_builtin_longjmp (buf_addr));
    1142                 :            :   else
    1143                 :            :     {
    1144                 :        356 :       fp = gen_rtx_MEM (Pmode, buf_addr);
    1145                 :        356 :       lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
    1146                 :        711 :                                                GET_MODE_SIZE (Pmode)));
    1147                 :            : 
    1148                 :        355 :       stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
    1149                 :        711 :                                                    2 * GET_MODE_SIZE (Pmode)));
    1150                 :        355 :       set_mem_alias_set (fp, setjmp_alias_set);
    1151                 :        355 :       set_mem_alias_set (lab, setjmp_alias_set);
    1152                 :        355 :       set_mem_alias_set (stack, setjmp_alias_set);
    1153                 :            : 
    1154                 :            :       /* Pick up FP, label, and SP from the block and jump.  This code is
    1155                 :            :          from expand_goto in stmt.c; see there for detailed comments.  */
    1156                 :        355 :       if (targetm.have_nonlocal_goto ())
    1157                 :            :         /* We have to pass a value to the nonlocal_goto pattern that will
    1158                 :            :            get copied into the static_chain pointer, but it does not matter
    1159                 :            :            what that value is, because builtin_setjmp does not use it.  */
    1160                 :          0 :         emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
    1161                 :            :       else
    1162                 :            :         {
    1163                 :        355 :           emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
    1164                 :        355 :           emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
    1165                 :            : 
    1166                 :        355 :           lab = copy_to_reg (lab);
    1167                 :            : 
    1168                 :            :           /* Restore the frame pointer and stack pointer.  We must use a
    1169                 :            :              temporary since the setjmp buffer may be a local.  */
    1170                 :        355 :           fp = copy_to_reg (fp);
    1171                 :        355 :           emit_stack_restore (SAVE_NONLOCAL, stack);
    1172                 :            : 
    1173                 :            :           /* Ensure the frame pointer move is not optimized.  */
    1174                 :        355 :           emit_insn (gen_blockage ());
    1175                 :        355 :           emit_clobber (hard_frame_pointer_rtx);
    1176                 :        355 :           emit_clobber (frame_pointer_rtx);
    1177                 :        355 :           emit_move_insn (hard_frame_pointer_rtx, fp);
    1178                 :            : 
    1179                 :        355 :           emit_use (hard_frame_pointer_rtx);
    1180                 :        355 :           emit_use (stack_pointer_rtx);
    1181                 :        355 :           emit_indirect_jump (lab);
    1182                 :            :         }
    1183                 :            :     }
    1184                 :            : 
    1185                 :            :   /* Search backwards and mark the jump insn as a non-local goto.
    1186                 :            :      Note that this precludes the use of __builtin_longjmp to a
    1187                 :            :      __builtin_setjmp target in the same function.  However, we've
    1188                 :            :      already cautioned the user that these functions are for
    1189                 :            :      internal exception handling use only.  */
    1190                 :       1065 :   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
    1191                 :            :     {
    1192                 :        710 :       gcc_assert (insn != last);
    1193                 :            : 
    1194                 :        710 :       if (JUMP_P (insn))
    1195                 :            :         {
    1196                 :        355 :           add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
    1197                 :        355 :           break;
    1198                 :            :         }
    1199                 :        355 :       else if (CALL_P (insn))
    1200                 :            :         break;
    1201                 :            :     }
    1202                 :        355 : }
    1203                 :            : 
    1204                 :            : static inline bool
    1205                 :     487128 : more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
    1206                 :            : {
    1207                 :     487128 :   return (iter->i < iter->n);
    1208                 :            : }
    1209                 :            : 
    1210                 :            : /* This function validates the types of a function call argument list
    1211                 :            :    against a specified list of tree_codes.  If the last specifier is a 0,
    1212                 :            :    that represents an ellipsis, otherwise the last specifier must be a
    1213                 :            :    VOID_TYPE.  */
    1214                 :            : 
    1215                 :            : static bool
    1216                 :     211474 : validate_arglist (const_tree callexpr, ...)
    1217                 :            : {
    1218                 :     211474 :   enum tree_code code;
    1219                 :     211474 :   bool res = 0;
    1220                 :     211474 :   va_list ap;
    1221                 :     211474 :   const_call_expr_arg_iterator iter;
    1222                 :     211474 :   const_tree arg;
    1223                 :            : 
    1224                 :     211474 :   va_start (ap, callexpr);
    1225                 :     211474 :   init_const_call_expr_arg_iterator (callexpr, &iter);
    1226                 :            : 
    1227                 :            :   /* Get a bitmap of pointer argument numbers declared attribute nonnull.  */
    1228                 :     211474 :   tree fn = CALL_EXPR_FN (callexpr);
    1229                 :     211474 :   bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
    1230                 :            : 
    1231                 :     764659 :   for (unsigned argno = 1; ; ++argno)
    1232                 :            :     {
    1233                 :     764659 :       code = (enum tree_code) va_arg (ap, int);
    1234                 :            : 
    1235                 :     764659 :       switch (code)
    1236                 :            :         {
    1237                 :       1848 :         case 0:
    1238                 :            :           /* This signifies an ellipses, any further arguments are all ok.  */
    1239                 :       1848 :           res = true;
    1240                 :       1848 :           goto end;
    1241                 :     209208 :         case VOID_TYPE:
    1242                 :            :           /* This signifies an endlink, if no arguments remain, return
    1243                 :            :              true, otherwise return false.  */
    1244                 :     209208 :           res = !more_const_call_expr_args_p (&iter);
    1245                 :     209208 :           goto end;
    1246                 :     326103 :         case POINTER_TYPE:
    1247                 :            :           /* The actual argument must be nonnull when either the whole
    1248                 :            :              called function has been declared nonnull, or when the formal
    1249                 :            :              argument corresponding to the actual argument has been.  */
    1250                 :     326103 :           if (argmap
    1251                 :     326103 :               && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
    1252                 :            :             {
    1253                 :     158134 :               arg = next_const_call_expr_arg (&iter);
    1254                 :     158134 :               if (!validate_arg (arg, code) || integer_zerop (arg))
    1255                 :        279 :                 goto end;
    1256                 :            :               break;
    1257                 :            :             }
    1258                 :            :           /* FALLTHRU */
    1259                 :     395469 :         default:
    1260                 :            :           /* If no parameters remain or the parameter's code does not
    1261                 :            :              match the specified code, return false.  Otherwise continue
    1262                 :            :              checking any remaining arguments.  */
    1263                 :     395469 :           arg = next_const_call_expr_arg (&iter);
    1264                 :     395469 :           if (!validate_arg (arg, code))
    1265                 :        139 :             goto end;
    1266                 :            :           break;
    1267                 :            :         }
    1268                 :            :     }
    1269                 :            : 
    1270                 :            :   /* We need gotos here since we can only have one VA_CLOSE in a
    1271                 :            :      function.  */
    1272                 :     211474 :  end: ;
    1273                 :     211474 :   va_end (ap);
    1274                 :            : 
    1275                 :     211474 :   BITMAP_FREE (argmap);
    1276                 :            : 
    1277                 :     211474 :   return res;
    1278                 :            : }
    1279                 :            : 
    1280                 :            : /* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
    1281                 :            :    and the address of the save area.  */
    1282                 :            : 
    1283                 :            : static rtx
    1284                 :        509 : expand_builtin_nonlocal_goto (tree exp)
    1285                 :            : {
    1286                 :        509 :   tree t_label, t_save_area;
    1287                 :        509 :   rtx r_label, r_save_area, r_fp, r_sp;
    1288                 :        509 :   rtx_insn *insn;
    1289                 :            : 
    1290                 :        509 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    1291                 :            :     return NULL_RTX;
    1292                 :            : 
    1293                 :        509 :   t_label = CALL_EXPR_ARG (exp, 0);
    1294                 :        509 :   t_save_area = CALL_EXPR_ARG (exp, 1);
    1295                 :            : 
    1296                 :        509 :   r_label = expand_normal (t_label);
    1297                 :       1018 :   r_label = convert_memory_address (Pmode, r_label);
    1298                 :        509 :   r_save_area = expand_normal (t_save_area);
    1299                 :       1018 :   r_save_area = convert_memory_address (Pmode, r_save_area);
    1300                 :            :   /* Copy the address of the save location to a register just in case it was
    1301                 :            :      based on the frame pointer.   */
    1302                 :        509 :   r_save_area = copy_to_reg (r_save_area);
    1303                 :        509 :   r_fp = gen_rtx_MEM (Pmode, r_save_area);
    1304                 :        509 :   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
    1305                 :        509 :                       plus_constant (Pmode, r_save_area,
    1306                 :       1018 :                                      GET_MODE_SIZE (Pmode)));
    1307                 :            : 
    1308                 :        509 :   crtl->has_nonlocal_goto = 1;
    1309                 :            : 
    1310                 :            :   /* ??? We no longer need to pass the static chain value, afaik.  */
    1311                 :        509 :   if (targetm.have_nonlocal_goto ())
    1312                 :          0 :     emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
    1313                 :            :   else
    1314                 :            :     {
    1315                 :        509 :       emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
    1316                 :        509 :       emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
    1317                 :            : 
    1318                 :        509 :       r_label = copy_to_reg (r_label);
    1319                 :            : 
    1320                 :            :       /* Restore the frame pointer and stack pointer.  We must use a
    1321                 :            :          temporary since the setjmp buffer may be a local.  */
    1322                 :        509 :       r_fp = copy_to_reg (r_fp);
    1323                 :        509 :       emit_stack_restore (SAVE_NONLOCAL, r_sp);
    1324                 :            : 
    1325                 :            :       /* Ensure the frame pointer move is not optimized.  */
    1326                 :        509 :       emit_insn (gen_blockage ());
    1327                 :        509 :       emit_clobber (hard_frame_pointer_rtx);
    1328                 :        509 :       emit_clobber (frame_pointer_rtx);
    1329                 :        509 :       emit_move_insn (hard_frame_pointer_rtx, r_fp);
    1330                 :            : 
    1331                 :            :       /* USE of hard_frame_pointer_rtx added for consistency;
    1332                 :            :          not clear if really needed.  */
    1333                 :        509 :       emit_use (hard_frame_pointer_rtx);
    1334                 :        509 :       emit_use (stack_pointer_rtx);
    1335                 :            : 
    1336                 :            :       /* If the architecture is using a GP register, we must
    1337                 :            :          conservatively assume that the target function makes use of it.
    1338                 :            :          The prologue of functions with nonlocal gotos must therefore
    1339                 :            :          initialize the GP register to the appropriate value, and we
    1340                 :            :          must then make sure that this value is live at the point
    1341                 :            :          of the jump.  (Note that this doesn't necessarily apply
    1342                 :            :          to targets with a nonlocal_goto pattern; they are free
    1343                 :            :          to implement it in their own way.  Note also that this is
    1344                 :            :          a no-op if the GP register is a global invariant.)  */
    1345                 :        509 :       unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
    1346                 :          0 :       if (regnum != INVALID_REGNUM && fixed_regs[regnum])
    1347                 :          0 :         emit_use (pic_offset_table_rtx);
    1348                 :            : 
    1349                 :        509 :       emit_indirect_jump (r_label);
    1350                 :            :     }
    1351                 :            : 
    1352                 :            :   /* Search backwards to the jump insn and mark it as a
    1353                 :            :      non-local goto.  */
    1354                 :       1527 :   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
    1355                 :            :     {
    1356                 :       1018 :       if (JUMP_P (insn))
    1357                 :            :         {
    1358                 :        509 :           add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
    1359                 :        509 :           break;
    1360                 :            :         }
    1361                 :        509 :       else if (CALL_P (insn))
    1362                 :            :         break;
    1363                 :            :     }
    1364                 :            : 
    1365                 :        509 :   return const0_rtx;
    1366                 :            : }
    1367                 :            : 
    1368                 :            : /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
    1369                 :            :    (not all will be used on all machines) that was passed to __builtin_setjmp.
    1370                 :            :    It updates the stack pointer in that block to the current value.  This is
    1371                 :            :    also called directly by the SJLJ exception handling code.  */
    1372                 :            : 
    1373                 :            : void
    1374                 :          0 : expand_builtin_update_setjmp_buf (rtx buf_addr)
    1375                 :            : {
    1376                 :          0 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
    1377                 :          0 :   buf_addr = convert_memory_address (Pmode, buf_addr);
    1378                 :          0 :   rtx stack_save
    1379                 :          0 :     = gen_rtx_MEM (sa_mode,
    1380                 :          0 :                    memory_address
    1381                 :            :                    (sa_mode,
    1382                 :            :                     plus_constant (Pmode, buf_addr,
    1383                 :          0 :                                    2 * GET_MODE_SIZE (Pmode))));
    1384                 :            : 
    1385                 :          0 :   emit_stack_save (SAVE_NONLOCAL, &stack_save);
    1386                 :          0 : }
    1387                 :            : 
    1388                 :            : /* Expand a call to __builtin_prefetch.  For a target that does not support
    1389                 :            :    data prefetch, evaluate the memory address argument in case it has side
    1390                 :            :    effects.  */
    1391                 :            : 
    1392                 :            : static void
    1393                 :       1848 : expand_builtin_prefetch (tree exp)
    1394                 :            : {
    1395                 :       1848 :   tree arg0, arg1, arg2;
    1396                 :       1848 :   int nargs;
    1397                 :       1848 :   rtx op0, op1, op2;
    1398                 :            : 
    1399                 :       1848 :   if (!validate_arglist (exp, POINTER_TYPE, 0))
    1400                 :            :     return;
    1401                 :            : 
    1402                 :       1848 :   arg0 = CALL_EXPR_ARG (exp, 0);
    1403                 :            : 
    1404                 :            :   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
    1405                 :            :      zero (read) and argument 2 (locality) defaults to 3 (high degree of
    1406                 :            :      locality).  */
    1407                 :       1848 :   nargs = call_expr_nargs (exp);
    1408                 :       1848 :   if (nargs > 1)
    1409                 :       1812 :     arg1 = CALL_EXPR_ARG (exp, 1);
    1410                 :            :   else
    1411                 :         36 :     arg1 = integer_zero_node;
    1412                 :       1848 :   if (nargs > 2)
    1413                 :       1787 :     arg2 = CALL_EXPR_ARG (exp, 2);
    1414                 :            :   else
    1415                 :         61 :     arg2 = integer_three_node;
    1416                 :            : 
    1417                 :            :   /* Argument 0 is an address.  */
    1418                 :       1896 :   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
    1419                 :            : 
    1420                 :            :   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
    1421                 :       1848 :   if (TREE_CODE (arg1) != INTEGER_CST)
    1422                 :            :     {
    1423                 :          0 :       error ("second argument to %<__builtin_prefetch%> must be a constant");
    1424                 :          0 :       arg1 = integer_zero_node;
    1425                 :            :     }
    1426                 :       1848 :   op1 = expand_normal (arg1);
    1427                 :            :   /* Argument 1 must be either zero or one.  */
    1428                 :       1848 :   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
    1429                 :            :     {
    1430                 :          3 :       warning (0, "invalid second argument to %<__builtin_prefetch%>;"
    1431                 :            :                " using zero");
    1432                 :          3 :       op1 = const0_rtx;
    1433                 :            :     }
    1434                 :            : 
    1435                 :            :   /* Argument 2 (locality) must be a compile-time constant int.  */
    1436                 :       1848 :   if (TREE_CODE (arg2) != INTEGER_CST)
    1437                 :            :     {
    1438                 :          0 :       error ("third argument to %<__builtin_prefetch%> must be a constant");
    1439                 :          0 :       arg2 = integer_zero_node;
    1440                 :            :     }
    1441                 :       1848 :   op2 = expand_normal (arg2);
    1442                 :            :   /* Argument 2 must be 0, 1, 2, or 3.  */
    1443                 :       1848 :   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
    1444                 :            :     {
    1445                 :          3 :       warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
    1446                 :          3 :       op2 = const0_rtx;
    1447                 :            :     }
    1448                 :            : 
    1449                 :       1848 :   if (targetm.have_prefetch ())
    1450                 :            :     {
    1451                 :       1848 :       class expand_operand ops[3];
    1452                 :            : 
    1453                 :       1848 :       create_address_operand (&ops[0], op0);
    1454                 :       1848 :       create_integer_operand (&ops[1], INTVAL (op1));
    1455                 :       1848 :       create_integer_operand (&ops[2], INTVAL (op2));
    1456                 :       1848 :       if (maybe_expand_insn (targetm.code_for_prefetch, 3, ops))
    1457                 :       1848 :         return;
    1458                 :            :     }
    1459                 :            : 
    1460                 :            :   /* Don't do anything with direct references to volatile memory, but
    1461                 :            :      generate code to handle other side effects.  */
    1462                 :          0 :   if (!MEM_P (op0) && side_effects_p (op0))
    1463                 :          0 :     emit_insn (op0);
    1464                 :            : }
    1465                 :            : 
    1466                 :            : /* Get a MEM rtx for expression EXP which is the address of an operand
    1467                 :            :    to be used in a string instruction (cmpstrsi, cpymemsi, ..).  LEN is
    1468                 :            :    the maximum length of the block of memory that might be accessed or
    1469                 :            :    NULL if unknown.  */
    1470                 :            : 
    1471                 :            : static rtx
    1472                 :     276889 : get_memory_rtx (tree exp, tree len)
    1473                 :            : {
    1474                 :     276889 :   tree orig_exp = exp;
    1475                 :     276889 :   rtx addr, mem;
    1476                 :            : 
    1477                 :            :   /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
    1478                 :            :      from its expression, for expr->a.b only <variable>.a.b is recorded.  */
    1479                 :     276889 :   if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
    1480                 :        972 :     exp = TREE_OPERAND (exp, 0);
    1481                 :            : 
    1482                 :     276889 :   addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    1483                 :     276889 :   mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
    1484                 :            : 
    1485                 :            :   /* Get an expression we can use to find the attributes to assign to MEM.
    1486                 :            :      First remove any nops.  */
    1487                 :     276889 :   while (CONVERT_EXPR_P (exp)
    1488                 :     276889 :          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
    1489                 :          0 :     exp = TREE_OPERAND (exp, 0);
    1490                 :            : 
    1491                 :            :   /* Build a MEM_REF representing the whole accessed area as a byte blob,
    1492                 :            :      (as builtin stringops may alias with anything).  */
    1493                 :     276889 :   exp = fold_build2 (MEM_REF,
    1494                 :            :                      build_array_type (char_type_node,
    1495                 :            :                                        build_range_type (sizetype,
    1496                 :            :                                                          size_one_node, len)),
    1497                 :            :                      exp, build_int_cst (ptr_type_node, 0));
    1498                 :            : 
    1499                 :            :   /* If the MEM_REF has no acceptable address, try to get the base object
    1500                 :            :      from the original address we got, and build an all-aliasing
    1501                 :            :      unknown-sized access to that one.  */
    1502                 :     276889 :   if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
    1503                 :     276817 :     set_mem_attributes (mem, exp, 0);
    1504                 :         72 :   else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
    1505                 :         72 :            && (exp = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
    1506                 :            :                                                      0))))
    1507                 :            :     {
    1508                 :         72 :       exp = build_fold_addr_expr (exp);
    1509                 :         72 :       exp = fold_build2 (MEM_REF,
    1510                 :            :                          build_array_type (char_type_node,
    1511                 :            :                                            build_range_type (sizetype,
    1512                 :            :                                                              size_zero_node,
    1513                 :            :                                                              NULL)),
    1514                 :            :                          exp, build_int_cst (ptr_type_node, 0));
    1515                 :         72 :       set_mem_attributes (mem, exp, 0);
    1516                 :            :     }
    1517                 :     276889 :   set_mem_alias_set (mem, 0);
    1518                 :     276889 :   return mem;
    1519                 :            : }
    1520                 :            : 
    1521                 :            : /* Built-in functions to perform an untyped call and return.  */
    1522                 :            : 
    1523                 :            : #define apply_args_mode \
    1524                 :            :   (this_target_builtins->x_apply_args_mode)
    1525                 :            : #define apply_result_mode \
    1526                 :            :   (this_target_builtins->x_apply_result_mode)
    1527                 :            : 
    1528                 :            : /* Return the size required for the block returned by __builtin_apply_args,
    1529                 :            :    and initialize apply_args_mode.  */
    1530                 :            : 
    1531                 :            : static int
    1532                 :        381 : apply_args_size (void)
    1533                 :            : {
    1534                 :        381 :   static int size = -1;
    1535                 :        381 :   int align;
    1536                 :        381 :   unsigned int regno;
    1537                 :            : 
    1538                 :            :   /* The values computed by this function never change.  */
    1539                 :        381 :   if (size < 0)
    1540                 :            :     {
    1541                 :            :       /* The first value is the incoming arg-pointer.  */
    1542                 :        207 :       size = GET_MODE_SIZE (Pmode);
    1543                 :            : 
    1544                 :            :       /* The second value is the structure value address unless this is
    1545                 :            :          passed as an "invisible" first argument.  */
    1546                 :        207 :       if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
    1547                 :          0 :         size += GET_MODE_SIZE (Pmode);
    1548                 :            : 
    1549                 :      15939 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1550                 :      15732 :         if (FUNCTION_ARG_REGNO_P (regno))
    1551                 :            :           {
    1552                 :       3105 :             fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
    1553                 :            : 
    1554                 :       3105 :             gcc_assert (mode != VOIDmode);
    1555                 :            : 
    1556                 :       3105 :             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1557                 :       3105 :             if (size % align != 0)
    1558                 :          1 :               size = CEIL (size, align) * align;
    1559                 :       3105 :             size += GET_MODE_SIZE (mode);
    1560                 :       3105 :             apply_args_mode[regno] = mode;
    1561                 :            :           }
    1562                 :            :         else
    1563                 :            :           {
    1564                 :      12627 :             apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
    1565                 :            :           }
    1566                 :            :     }
    1567                 :        381 :   return size;
    1568                 :            : }
    1569                 :            : 
    1570                 :            : /* Return the size required for the block returned by __builtin_apply,
    1571                 :            :    and initialize apply_result_mode.  */
    1572                 :            : 
    1573                 :            : static int
    1574                 :        312 : apply_result_size (void)
    1575                 :            : {
    1576                 :        312 :   static int size = -1;
    1577                 :        312 :   int align, regno;
    1578                 :            : 
    1579                 :            :   /* The values computed by this function never change.  */
    1580                 :        312 :   if (size < 0)
    1581                 :            :     {
    1582                 :        214 :       size = 0;
    1583                 :            : 
    1584                 :      16478 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1585                 :      16264 :         if (targetm.calls.function_value_regno_p (regno))
    1586                 :            :           {
    1587                 :       1712 :             fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
    1588                 :            : 
    1589                 :       1712 :             gcc_assert (mode != VOIDmode);
    1590                 :            : 
    1591                 :       1712 :             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1592                 :       1712 :             if (size % align != 0)
    1593                 :          0 :               size = CEIL (size, align) * align;
    1594                 :       1712 :             size += GET_MODE_SIZE (mode);
    1595                 :       1712 :             apply_result_mode[regno] = mode;
    1596                 :            :           }
    1597                 :            :         else
    1598                 :      14552 :           apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
    1599                 :            : 
    1600                 :            :       /* Allow targets that use untyped_call and untyped_return to override
    1601                 :            :          the size so that machine-specific information can be stored here.  */
    1602                 :            : #ifdef APPLY_RESULT_SIZE
    1603                 :        214 :       size = APPLY_RESULT_SIZE;
    1604                 :            : #endif
    1605                 :            :     }
    1606                 :        312 :   return size;
    1607                 :            : }
    1608                 :            : 
    1609                 :            : /* Create a vector describing the result block RESULT.  If SAVEP is true,
    1610                 :            :    the result block is used to save the values; otherwise it is used to
    1611                 :            :    restore the values.  */
    1612                 :            : 
    1613                 :            : static rtx
    1614                 :        206 : result_vector (int savep, rtx result)
    1615                 :            : {
    1616                 :        206 :   int regno, size, align, nelts;
    1617                 :        206 :   fixed_size_mode mode;
    1618                 :        206 :   rtx reg, mem;
    1619                 :        206 :   rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
    1620                 :            : 
    1621                 :        206 :   size = nelts = 0;
    1622                 :      15862 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1623                 :      15656 :     if ((mode = apply_result_mode[regno]) != VOIDmode)
    1624                 :            :       {
    1625                 :       1648 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1626                 :       1648 :         if (size % align != 0)
    1627                 :          0 :           size = CEIL (size, align) * align;
    1628                 :       1648 :         reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
    1629                 :       1648 :         mem = adjust_address (result, mode, size);
    1630                 :       3296 :         savevec[nelts++] = (savep
    1631                 :       3296 :                             ? gen_rtx_SET (mem, reg)
    1632                 :          0 :                             : gen_rtx_SET (reg, mem));
    1633                 :       3296 :         size += GET_MODE_SIZE (mode);
    1634                 :            :       }
    1635                 :        206 :   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
    1636                 :            : }
    1637                 :            : 
    1638                 :            : /* Save the state required to perform an untyped call with the same
    1639                 :            :    arguments as were passed to the current function.  */
    1640                 :            : 
    1641                 :            : static rtx
    1642                 :        175 : expand_builtin_apply_args_1 (void)
    1643                 :            : {
    1644                 :        175 :   rtx registers, tem;
    1645                 :        175 :   int size, align, regno;
    1646                 :        175 :   fixed_size_mode mode;
    1647                 :        175 :   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
    1648                 :            : 
    1649                 :            :   /* Create a block where the arg-pointer, structure value address,
    1650                 :            :      and argument registers can be saved.  */
    1651                 :        175 :   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
    1652                 :            : 
    1653                 :            :   /* Walk past the arg-pointer and structure value address.  */
    1654                 :        175 :   size = GET_MODE_SIZE (Pmode);
    1655                 :        175 :   if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
    1656                 :          0 :     size += GET_MODE_SIZE (Pmode);
    1657                 :            : 
    1658                 :            :   /* Save each register used in calling a function to the block.  */
    1659                 :      13475 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1660                 :      13300 :     if ((mode = apply_args_mode[regno]) != VOIDmode)
    1661                 :            :       {
    1662                 :       2625 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1663                 :       2625 :         if (size % align != 0)
    1664                 :          1 :           size = CEIL (size, align) * align;
    1665                 :            : 
    1666                 :       2625 :         tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
    1667                 :            : 
    1668                 :       2625 :         emit_move_insn (adjust_address (registers, mode, size), tem);
    1669                 :       5250 :         size += GET_MODE_SIZE (mode);
    1670                 :            :       }
    1671                 :            : 
    1672                 :            :   /* Save the arg pointer to the block.  */
    1673                 :        175 :   tem = copy_to_reg (crtl->args.internal_arg_pointer);
    1674                 :            :   /* We need the pointer as the caller actually passed them to us, not
    1675                 :            :      as we might have pretended they were passed.  Make sure it's a valid
    1676                 :            :      operand, as emit_move_insn isn't expected to handle a PLUS.  */
    1677                 :        175 :   if (STACK_GROWS_DOWNWARD)
    1678                 :        175 :     tem
    1679                 :        175 :       = force_operand (plus_constant (Pmode, tem,
    1680                 :            :                                       crtl->args.pretend_args_size),
    1681                 :            :                        NULL_RTX);
    1682                 :        175 :   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
    1683                 :            : 
    1684                 :        175 :   size = GET_MODE_SIZE (Pmode);
    1685                 :            : 
    1686                 :            :   /* Save the structure value address unless this is passed as an
    1687                 :            :      "invisible" first argument.  */
    1688                 :        175 :   if (struct_incoming_value)
    1689                 :          0 :     emit_move_insn (adjust_address (registers, Pmode, size),
    1690                 :            :                     copy_to_reg (struct_incoming_value));
    1691                 :            : 
    1692                 :            :   /* Return the address of the block.  */
    1693                 :        175 :   return copy_addr_to_reg (XEXP (registers, 0));
    1694                 :            : }
    1695                 :            : 
    1696                 :            : /* __builtin_apply_args returns block of memory allocated on
    1697                 :            :    the stack into which is stored the arg pointer, structure
    1698                 :            :    value address, static chain, and all the registers that might
    1699                 :            :    possibly be used in performing a function call.  The code is
    1700                 :            :    moved to the start of the function so the incoming values are
    1701                 :            :    saved.  */
    1702                 :            : 
    1703                 :            : static rtx
    1704                 :        175 : expand_builtin_apply_args (void)
    1705                 :            : {
    1706                 :            :   /* Don't do __builtin_apply_args more than once in a function.
    1707                 :            :      Save the result of the first call and reuse it.  */
    1708                 :        175 :   if (apply_args_value != 0)
    1709                 :            :     return apply_args_value;
    1710                 :        175 :   {
    1711                 :            :     /* When this function is called, it means that registers must be
    1712                 :            :        saved on entry to this function.  So we migrate the
    1713                 :            :        call to the first insn of this function.  */
    1714                 :        175 :     rtx temp;
    1715                 :            : 
    1716                 :        175 :     start_sequence ();
    1717                 :        175 :     temp = expand_builtin_apply_args_1 ();
    1718                 :        175 :     rtx_insn *seq = get_insns ();
    1719                 :        175 :     end_sequence ();
    1720                 :            : 
    1721                 :        175 :     apply_args_value = temp;
    1722                 :            : 
    1723                 :            :     /* Put the insns after the NOTE that starts the function.
    1724                 :            :        If this is inside a start_sequence, make the outer-level insn
    1725                 :            :        chain current, so the code is placed at the start of the
    1726                 :            :        function.  If internal_arg_pointer is a non-virtual pseudo,
    1727                 :            :        it needs to be placed after the function that initializes
    1728                 :            :        that pseudo.  */
    1729                 :        175 :     push_topmost_sequence ();
    1730                 :        175 :     if (REG_P (crtl->args.internal_arg_pointer)
    1731                 :        175 :         && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
    1732                 :          0 :       emit_insn_before (seq, parm_birth_insn);
    1733                 :            :     else
    1734                 :        175 :       emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
    1735                 :        175 :     pop_topmost_sequence ();
    1736                 :        175 :     return temp;
    1737                 :            :   }
    1738                 :            : }
    1739                 :            : 
    1740                 :            : /* Perform an untyped call and save the state required to perform an
    1741                 :            :    untyped return of whatever value was returned by the given function.  */
    1742                 :            : 
    1743                 :            : static rtx
    1744                 :        206 : expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
    1745                 :            : {
    1746                 :        206 :   int size, align, regno;
    1747                 :        206 :   fixed_size_mode mode;
    1748                 :        206 :   rtx incoming_args, result, reg, dest, src;
    1749                 :        206 :   rtx_call_insn *call_insn;
    1750                 :        206 :   rtx old_stack_level = 0;
    1751                 :        206 :   rtx call_fusage = 0;
    1752                 :        206 :   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
    1753                 :            : 
    1754                 :        412 :   arguments = convert_memory_address (Pmode, arguments);
    1755                 :            : 
    1756                 :            :   /* Create a block where the return registers can be saved.  */
    1757                 :        206 :   result = assign_stack_local (BLKmode, apply_result_size (), -1);
    1758                 :            : 
    1759                 :            :   /* Fetch the arg pointer from the ARGUMENTS block.  */
    1760                 :        206 :   incoming_args = gen_reg_rtx (Pmode);
    1761                 :        206 :   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
    1762                 :        206 :   if (!STACK_GROWS_DOWNWARD)
    1763                 :            :     incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
    1764                 :            :                                          incoming_args, 0, OPTAB_LIB_WIDEN);
    1765                 :            : 
    1766                 :            :   /* Push a new argument block and copy the arguments.  Do not allow
    1767                 :            :      the (potential) memcpy call below to interfere with our stack
    1768                 :            :      manipulations.  */
    1769                 :        206 :   do_pending_stack_adjust ();
    1770                 :        206 :   NO_DEFER_POP;
    1771                 :            : 
    1772                 :            :   /* Save the stack with nonlocal if available.  */
    1773                 :        206 :   if (targetm.have_save_stack_nonlocal ())
    1774                 :        206 :     emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
    1775                 :            :   else
    1776                 :          0 :     emit_stack_save (SAVE_BLOCK, &old_stack_level);
    1777                 :            : 
    1778                 :            :   /* Allocate a block of memory onto the stack and copy the memory
    1779                 :            :      arguments to the outgoing arguments address.  We can pass TRUE
    1780                 :            :      as the 4th argument because we just saved the stack pointer
    1781                 :            :      and will restore it right after the call.  */
    1782                 :        412 :   allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
    1783                 :            : 
    1784                 :            :   /* Set DRAP flag to true, even though allocate_dynamic_stack_space
    1785                 :            :      may have already set current_function_calls_alloca to true.
    1786                 :            :      current_function_calls_alloca won't be set if argsize is zero,
    1787                 :            :      so we have to guarantee need_drap is true here.  */
    1788                 :        206 :   if (SUPPORTS_STACK_ALIGNMENT)
    1789                 :        206 :     crtl->need_drap = true;
    1790                 :            : 
    1791                 :        206 :   dest = virtual_outgoing_args_rtx;
    1792                 :        206 :   if (!STACK_GROWS_DOWNWARD)
    1793                 :            :     {
    1794                 :            :       if (CONST_INT_P (argsize))
    1795                 :            :         dest = plus_constant (Pmode, dest, -INTVAL (argsize));
    1796                 :            :       else
    1797                 :            :         dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
    1798                 :            :     }
    1799                 :        206 :   dest = gen_rtx_MEM (BLKmode, dest);
    1800                 :        206 :   set_mem_align (dest, PARM_BOUNDARY);
    1801                 :        206 :   src = gen_rtx_MEM (BLKmode, incoming_args);
    1802                 :        206 :   set_mem_align (src, PARM_BOUNDARY);
    1803                 :        206 :   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
    1804                 :            : 
    1805                 :            :   /* Refer to the argument block.  */
    1806                 :        206 :   apply_args_size ();
    1807                 :        206 :   arguments = gen_rtx_MEM (BLKmode, arguments);
    1808                 :        206 :   set_mem_align (arguments, PARM_BOUNDARY);
    1809                 :            : 
    1810                 :            :   /* Walk past the arg-pointer and structure value address.  */
    1811                 :        206 :   size = GET_MODE_SIZE (Pmode);
    1812                 :        206 :   if (struct_value)
    1813                 :          0 :     size += GET_MODE_SIZE (Pmode);
    1814                 :            : 
    1815                 :            :   /* Restore each of the registers previously saved.  Make USE insns
    1816                 :            :      for each of these registers for use in making the call.  */
    1817                 :      15862 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1818                 :      15656 :     if ((mode = apply_args_mode[regno]) != VOIDmode)
    1819                 :            :       {
    1820                 :       3090 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1821                 :       3090 :         if (size % align != 0)
    1822                 :          0 :           size = CEIL (size, align) * align;
    1823                 :       3090 :         reg = gen_rtx_REG (mode, regno);
    1824                 :       3090 :         emit_move_insn (reg, adjust_address (arguments, mode, size));
    1825                 :       3090 :         use_reg (&call_fusage, reg);
    1826                 :       6180 :         size += GET_MODE_SIZE (mode);
    1827                 :            :       }
    1828                 :            : 
    1829                 :            :   /* Restore the structure value address unless this is passed as an
    1830                 :            :      "invisible" first argument.  */
    1831                 :        206 :   size = GET_MODE_SIZE (Pmode);
    1832                 :        206 :   if (struct_value)
    1833                 :            :     {
    1834                 :          0 :       rtx value = gen_reg_rtx (Pmode);
    1835                 :          0 :       emit_move_insn (value, adjust_address (arguments, Pmode, size));
    1836                 :          0 :       emit_move_insn (struct_value, value);
    1837                 :          0 :       if (REG_P (struct_value))
    1838                 :          0 :         use_reg (&call_fusage, struct_value);
    1839                 :            :     }
    1840                 :            : 
    1841                 :            :   /* All arguments and registers used for the call are set up by now!  */
    1842                 :        206 :   function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
    1843                 :            : 
    1844                 :            :   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
    1845                 :            :      and we don't want to load it into a register as an optimization,
    1846                 :            :      because prepare_call_address already did it if it should be done.  */
    1847                 :        206 :   if (GET_CODE (function) != SYMBOL_REF)
    1848                 :         25 :     function = memory_address (FUNCTION_MODE, function);
    1849                 :            : 
    1850                 :            :   /* Generate the actual call instruction and save the return value.  */
    1851                 :        206 :   if (targetm.have_untyped_call ())
    1852                 :            :     {
    1853                 :        206 :       rtx mem = gen_rtx_MEM (FUNCTION_MODE, function);
    1854                 :        206 :       emit_call_insn (targetm.gen_untyped_call (mem, result,
    1855                 :            :                                                 result_vector (1, result)));
    1856                 :            :     }
    1857                 :          0 :   else if (targetm.have_call_value ())
    1858                 :            :     {
    1859                 :            :       rtx valreg = 0;
    1860                 :            : 
    1861                 :            :       /* Locate the unique return register.  It is not possible to
    1862                 :            :          express a call that sets more than one return register using
    1863                 :            :          call_value; use untyped_call for that.  In fact, untyped_call
    1864                 :            :          only needs to save the return registers in the given block.  */
    1865                 :          0 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1866                 :          0 :         if ((mode = apply_result_mode[regno]) != VOIDmode)
    1867                 :            :           {
    1868                 :          0 :             gcc_assert (!valreg); /* have_untyped_call required.  */
    1869                 :            : 
    1870                 :          0 :             valreg = gen_rtx_REG (mode, regno);
    1871                 :            :           }
    1872                 :            : 
    1873                 :          0 :       emit_insn (targetm.gen_call_value (valreg,
    1874                 :            :                                          gen_rtx_MEM (FUNCTION_MODE, function),
    1875                 :            :                                          const0_rtx, NULL_RTX, const0_rtx));
    1876                 :            : 
    1877                 :          0 :       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
    1878                 :            :     }
    1879                 :            :   else
    1880                 :          0 :     gcc_unreachable ();
    1881                 :            : 
    1882                 :            :   /* Find the CALL insn we just emitted, and attach the register usage
    1883                 :            :      information.  */
    1884                 :        206 :   call_insn = last_call_insn ();
    1885                 :        206 :   add_function_usage_to (call_insn, call_fusage);
    1886                 :            : 
    1887                 :            :   /* Restore the stack.  */
    1888                 :        206 :   if (targetm.have_save_stack_nonlocal ())
    1889                 :        206 :     emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
    1890                 :            :   else
    1891                 :          0 :     emit_stack_restore (SAVE_BLOCK, old_stack_level);
    1892                 :        206 :   fixup_args_size_notes (call_insn, get_last_insn (), 0);
    1893                 :            : 
    1894                 :        206 :   OK_DEFER_POP;
    1895                 :            : 
    1896                 :            :   /* Return the address of the result block.  */
    1897                 :        206 :   result = copy_addr_to_reg (XEXP (result, 0));
    1898                 :        206 :   return convert_memory_address (ptr_mode, result);
    1899                 :            : }
    1900                 :            : 
    1901                 :            : /* Perform an untyped return.  */
    1902                 :            : 
    1903                 :            : static void
    1904                 :        106 : expand_builtin_return (rtx result)
    1905                 :            : {
    1906                 :        106 :   int size, align, regno;
    1907                 :        106 :   fixed_size_mode mode;
    1908                 :        106 :   rtx reg;
    1909                 :        106 :   rtx_insn *call_fusage = 0;
    1910                 :            : 
    1911                 :        212 :   result = convert_memory_address (Pmode, result);
    1912                 :            : 
    1913                 :        106 :   apply_result_size ();
    1914                 :        106 :   result = gen_rtx_MEM (BLKmode, result);
    1915                 :            : 
    1916                 :        106 :   if (targetm.have_untyped_return ())
    1917                 :            :     {
    1918                 :          0 :       rtx vector = result_vector (0, result);
    1919                 :          0 :       emit_jump_insn (targetm.gen_untyped_return (result, vector));
    1920                 :          0 :       emit_barrier ();
    1921                 :          0 :       return;
    1922                 :            :     }
    1923                 :            : 
    1924                 :            :   /* Restore the return value and note that each value is used.  */
    1925                 :            :   size = 0;
    1926                 :       8162 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1927                 :       8056 :     if ((mode = apply_result_mode[regno]) != VOIDmode)
    1928                 :            :       {
    1929                 :        848 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1930                 :        848 :         if (size % align != 0)
    1931                 :          0 :           size = CEIL (size, align) * align;
    1932                 :        848 :         reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
    1933                 :        848 :         emit_move_insn (reg, adjust_address (result, mode, size));
    1934                 :            : 
    1935                 :        848 :         push_to_sequence (call_fusage);
    1936                 :        848 :         emit_use (reg);
    1937                 :        848 :         call_fusage = get_insns ();
    1938                 :        848 :         end_sequence ();
    1939                 :       1696 :         size += GET_MODE_SIZE (mode);
    1940                 :            :       }
    1941                 :            : 
    1942                 :            :   /* Put the USE insns before the return.  */
    1943                 :        106 :   emit_insn (call_fusage);
    1944                 :            : 
    1945                 :            :   /* Return whatever values was restored by jumping directly to the end
    1946                 :            :      of the function.  */
    1947                 :        106 :   expand_naked_return ();
    1948                 :            : }
    1949                 :            : 
    1950                 :            : /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
    1951                 :            : 
    1952                 :            : static enum type_class
    1953                 :       2068 : type_to_class (tree type)
    1954                 :            : {
    1955                 :       2068 :   switch (TREE_CODE (type))
    1956                 :            :     {
    1957                 :            :     case VOID_TYPE:        return void_type_class;
    1958                 :        825 :     case INTEGER_TYPE:     return integer_type_class;
    1959                 :          0 :     case ENUMERAL_TYPE:    return enumeral_type_class;
    1960                 :          0 :     case BOOLEAN_TYPE:     return boolean_type_class;
    1961                 :       1151 :     case POINTER_TYPE:     return pointer_type_class;
    1962                 :          0 :     case REFERENCE_TYPE:   return reference_type_class;
    1963                 :          0 :     case OFFSET_TYPE:      return offset_type_class;
    1964                 :         92 :     case REAL_TYPE:        return real_type_class;
    1965                 :          0 :     case COMPLEX_TYPE:     return complex_type_class;
    1966                 :          0 :     case FUNCTION_TYPE:    return function_type_class;
    1967                 :          0 :     case METHOD_TYPE:      return method_type_class;
    1968                 :          0 :     case RECORD_TYPE:      return record_type_class;
    1969                 :          0 :     case UNION_TYPE:
    1970                 :          0 :     case QUAL_UNION_TYPE:  return union_type_class;
    1971                 :          0 :     case ARRAY_TYPE:       return (TYPE_STRING_FLAG (type)
    1972                 :          0 :                                    ? string_type_class : array_type_class);
    1973                 :          0 :     case LANG_TYPE:        return lang_type_class;
    1974                 :          0 :     default:               return no_type_class;
    1975                 :            :     }
    1976                 :            : }
    1977                 :            : 
    1978                 :            : /* Expand a call EXP to __builtin_classify_type.  */
    1979                 :            : 
    1980                 :            : static rtx
    1981                 :          0 : expand_builtin_classify_type (tree exp)
    1982                 :            : {
    1983                 :          0 :   if (call_expr_nargs (exp))
    1984                 :          0 :     return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
    1985                 :          0 :   return GEN_INT (no_type_class);
    1986                 :            : }
    1987                 :            : 
    1988                 :            : /* This helper macro, meant to be used in mathfn_built_in below, determines
    1989                 :            :    which among a set of builtin math functions is appropriate for a given type
    1990                 :            :    mode.  The `F' (float) and `L' (long double) are automatically generated
    1991                 :            :    from the 'double' case.  If a function supports the _Float<N> and _Float<N>X
    1992                 :            :    types, there are additional types that are considered with 'F32', 'F64',
    1993                 :            :    'F128', etc. suffixes.  */
    1994                 :            : #define CASE_MATHFN(MATHFN) \
    1995                 :            :   CASE_CFN_##MATHFN: \
    1996                 :            :   fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
    1997                 :            :   fcodel = BUILT_IN_##MATHFN##L ; break;
    1998                 :            : /* Similar to the above, but also add support for the _Float<N> and _Float<N>X
    1999                 :            :    types.  */
    2000                 :            : #define CASE_MATHFN_FLOATN(MATHFN) \
    2001                 :            :   CASE_CFN_##MATHFN: \
    2002                 :            :   fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
    2003                 :            :   fcodel = BUILT_IN_##MATHFN##L ; fcodef16 = BUILT_IN_##MATHFN##F16 ; \
    2004                 :            :   fcodef32 = BUILT_IN_##MATHFN##F32; fcodef64 = BUILT_IN_##MATHFN##F64 ; \
    2005                 :            :   fcodef128 = BUILT_IN_##MATHFN##F128 ; fcodef32x = BUILT_IN_##MATHFN##F32X ; \
    2006                 :            :   fcodef64x = BUILT_IN_##MATHFN##F64X ; fcodef128x = BUILT_IN_##MATHFN##F128X ;\
    2007                 :            :   break;
    2008                 :            : /* Similar to above, but appends _R after any F/L suffix.  */
    2009                 :            : #define CASE_MATHFN_REENT(MATHFN) \
    2010                 :            :   case CFN_BUILT_IN_##MATHFN##_R: \
    2011                 :            :   case CFN_BUILT_IN_##MATHFN##F_R: \
    2012                 :            :   case CFN_BUILT_IN_##MATHFN##L_R: \
    2013                 :            :   fcode = BUILT_IN_##MATHFN##_R; fcodef = BUILT_IN_##MATHFN##F_R ; \
    2014                 :            :   fcodel = BUILT_IN_##MATHFN##L_R ; break;
    2015                 :            : 
    2016                 :            : /* Return a function equivalent to FN but operating on floating-point
    2017                 :            :    values of type TYPE, or END_BUILTINS if no such function exists.
    2018                 :            :    This is purely an operation on function codes; it does not guarantee
    2019                 :            :    that the target actually has an implementation of the function.  */
    2020                 :            : 
    2021                 :            : static built_in_function
    2022                 :      45628 : mathfn_built_in_2 (tree type, combined_fn fn)
    2023                 :            : {
    2024                 :      45628 :   tree mtype;
    2025                 :      45628 :   built_in_function fcode, fcodef, fcodel;
    2026                 :      45628 :   built_in_function fcodef16 = END_BUILTINS;
    2027                 :      45628 :   built_in_function fcodef32 = END_BUILTINS;
    2028                 :      45628 :   built_in_function fcodef64 = END_BUILTINS;
    2029                 :      45628 :   built_in_function fcodef128 = END_BUILTINS;
    2030                 :      45628 :   built_in_function fcodef32x = END_BUILTINS;
    2031                 :      45628 :   built_in_function fcodef64x = END_BUILTINS;
    2032                 :      45628 :   built_in_function fcodef128x = END_BUILTINS;
    2033                 :            : 
    2034                 :      45628 :   switch (fn)
    2035                 :            :     {
    2036                 :            :     CASE_MATHFN (ACOS)
    2037                 :         54 :     CASE_MATHFN (ACOSH)
    2038                 :         61 :     CASE_MATHFN (ASIN)
    2039                 :         54 :     CASE_MATHFN (ASINH)
    2040                 :         58 :     CASE_MATHFN (ATAN)
    2041                 :        802 :     CASE_MATHFN (ATAN2)
    2042                 :         54 :     CASE_MATHFN (ATANH)
    2043                 :        350 :     CASE_MATHFN (CBRT)
    2044                 :        100 :     CASE_MATHFN_FLOATN (CEIL)
    2045                 :        326 :     CASE_MATHFN (CEXPI)
    2046                 :          0 :     CASE_MATHFN_FLOATN (COPYSIGN)
    2047                 :         62 :     CASE_MATHFN (COS)
    2048                 :         54 :     CASE_MATHFN (COSH)
    2049                 :          0 :     CASE_MATHFN (DREM)
    2050                 :         54 :     CASE_MATHFN (ERF)
    2051                 :         54 :     CASE_MATHFN (ERFC)
    2052                 :         74 :     CASE_MATHFN (EXP)
    2053                 :          0 :     CASE_MATHFN (EXP10)
    2054                 :         54 :     CASE_MATHFN (EXP2)
    2055                 :         58 :     CASE_MATHFN (EXPM1)
    2056                 :         19 :     CASE_MATHFN (FABS)
    2057                 :          0 :     CASE_MATHFN (FDIM)
    2058                 :        103 :     CASE_MATHFN_FLOATN (FLOOR)
    2059                 :          0 :     CASE_MATHFN_FLOATN (FMA)
    2060                 :          0 :     CASE_MATHFN_FLOATN (FMAX)
    2061                 :          0 :     CASE_MATHFN_FLOATN (FMIN)
    2062                 :          4 :     CASE_MATHFN (FMOD)
    2063                 :          0 :     CASE_MATHFN (FREXP)
    2064                 :          0 :     CASE_MATHFN (GAMMA)
    2065                 :          0 :     CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */
    2066                 :          0 :     CASE_MATHFN (HUGE_VAL)
    2067                 :          0 :     CASE_MATHFN (HYPOT)
    2068                 :          7 :     CASE_MATHFN (ILOGB)
    2069                 :         18 :     CASE_MATHFN (ICEIL)
    2070                 :         19 :     CASE_MATHFN (IFLOOR)
    2071                 :          0 :     CASE_MATHFN (INF)
    2072                 :         23 :     CASE_MATHFN (IRINT)
    2073                 :         22 :     CASE_MATHFN (IROUND)
    2074                 :          0 :     CASE_MATHFN (ISINF)
    2075                 :          0 :     CASE_MATHFN (J0)
    2076                 :          0 :     CASE_MATHFN (J1)
    2077                 :          0 :     CASE_MATHFN (JN)
    2078                 :         83 :     CASE_MATHFN (LCEIL)
    2079                 :         10 :     CASE_MATHFN (LDEXP)
    2080                 :         84 :     CASE_MATHFN (LFLOOR)
    2081                 :          0 :     CASE_MATHFN (LGAMMA)
    2082                 :          0 :     CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */
    2083                 :          0 :     CASE_MATHFN (LLCEIL)
    2084                 :          0 :     CASE_MATHFN (LLFLOOR)
    2085                 :          0 :     CASE_MATHFN (LLRINT)
    2086                 :          0 :     CASE_MATHFN (LLROUND)
    2087                 :         73 :     CASE_MATHFN (LOG)
    2088                 :         58 :     CASE_MATHFN (LOG10)
    2089                 :         58 :     CASE_MATHFN (LOG1P)
    2090                 :         54 :     CASE_MATHFN (LOG2)
    2091                 :         54 :     CASE_MATHFN (LOGB)
    2092                 :        154 :     CASE_MATHFN (LRINT)
    2093                 :        130 :     CASE_MATHFN (LROUND)
    2094                 :          0 :     CASE_MATHFN (MODF)
    2095                 :          0 :     CASE_MATHFN (NAN)
    2096                 :          0 :     CASE_MATHFN (NANS)
    2097                 :          0 :     CASE_MATHFN_FLOATN (NEARBYINT)
    2098                 :          0 :     CASE_MATHFN (NEXTAFTER)
    2099                 :          0 :     CASE_MATHFN (NEXTTOWARD)
    2100                 :          2 :     CASE_MATHFN (POW)
    2101                 :      41215 :     CASE_MATHFN (POWI)
    2102                 :          0 :     CASE_MATHFN (POW10)
    2103                 :          0 :     CASE_MATHFN (REMAINDER)
    2104                 :          0 :     CASE_MATHFN (REMQUO)
    2105                 :          0 :     CASE_MATHFN_FLOATN (RINT)
    2106                 :          0 :     CASE_MATHFN_FLOATN (ROUND)
    2107                 :          0 :     CASE_MATHFN_FLOATN (ROUNDEVEN)
    2108                 :          0 :     CASE_MATHFN (SCALB)
    2109                 :          0 :     CASE_MATHFN (SCALBLN)
    2110                 :          0 :     CASE_MATHFN (SCALBN)
    2111                 :          0 :     CASE_MATHFN (SIGNBIT)
    2112                 :          0 :     CASE_MATHFN (SIGNIFICAND)
    2113                 :         65 :     CASE_MATHFN (SIN)
    2114                 :          0 :     CASE_MATHFN (SINCOS)
    2115                 :         54 :     CASE_MATHFN (SINH)
    2116                 :        826 :     CASE_MATHFN_FLOATN (SQRT)
    2117                 :         58 :     CASE_MATHFN (TAN)
    2118                 :         54 :     CASE_MATHFN (TANH)
    2119                 :         54 :     CASE_MATHFN (TGAMMA)
    2120                 :          0 :     CASE_MATHFN_FLOATN (TRUNC)
    2121                 :          0 :     CASE_MATHFN (Y0)
    2122                 :          0 :     CASE_MATHFN (Y1)
    2123                 :          0 :     CASE_MATHFN (YN)
    2124                 :            : 
    2125                 :            :     default:
    2126                 :            :       return END_BUILTINS;
    2127                 :            :     }
    2128                 :            : 
    2129                 :      45628 :   mtype = TYPE_MAIN_VARIANT (type);
    2130                 :      45628 :   if (mtype == double_type_node)
    2131                 :            :     return fcode;
    2132                 :      39183 :   else if (mtype == float_type_node)
    2133                 :            :     return fcodef;
    2134                 :      32515 :   else if (mtype == long_double_type_node)
    2135                 :            :     return fcodel;
    2136                 :      27829 :   else if (mtype == float16_type_node)
    2137                 :            :     return fcodef16;
    2138                 :      27829 :   else if (mtype == float32_type_node)
    2139                 :            :     return fcodef32;
    2140                 :      27829 :   else if (mtype == float64_type_node)
    2141                 :            :     return fcodef64;
    2142                 :      27829 :   else if (mtype == float128_type_node)
    2143                 :            :     return fcodef128;
    2144                 :      24229 :   else if (mtype == float32x_type_node)
    2145                 :            :     return fcodef32x;
    2146                 :      24229 :   else if (mtype == float64x_type_node)
    2147                 :            :     return fcodef64x;
    2148                 :      24229 :   else if (mtype == float128x_type_node)
    2149                 :            :     return fcodef128x;
    2150                 :            :   else
    2151                 :      24229 :     return END_BUILTINS;
    2152                 :            : }
    2153                 :            : 
    2154                 :            : /* Return mathematic function equivalent to FN but operating directly on TYPE,
    2155                 :            :    if available.  If IMPLICIT_P is true use the implicit builtin declaration,
    2156                 :            :    otherwise use the explicit declaration.  If we can't do the conversion,
    2157                 :            :    return null.  */
    2158                 :            : 
    2159                 :            : static tree
    2160                 :      45482 : mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
    2161                 :            : {
    2162                 :      45482 :   built_in_function fcode2 = mathfn_built_in_2 (type, fn);
    2163                 :      45482 :   if (fcode2 == END_BUILTINS)
    2164                 :            :     return NULL_TREE;
    2165                 :            : 
    2166                 :      17653 :   if (implicit_p && !builtin_decl_implicit_p (fcode2))
    2167                 :            :     return NULL_TREE;
    2168                 :            : 
    2169                 :      17604 :   return builtin_decl_explicit (fcode2);
    2170                 :            : }
    2171                 :            : 
    2172                 :            : /* Like mathfn_built_in_1, but always use the implicit array.  */
    2173                 :            : 
    2174                 :            : tree
    2175                 :          8 : mathfn_built_in (tree type, combined_fn fn)
    2176                 :            : {
    2177                 :          8 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
    2178                 :            : }
    2179                 :            : 
    2180                 :            : /* Like mathfn_built_in_1, but take a built_in_function and
    2181                 :            :    always use the implicit array.  */
    2182                 :            : 
    2183                 :            : tree
    2184                 :      45420 : mathfn_built_in (tree type, enum built_in_function fn)
    2185                 :            : {
    2186                 :      45420 :   return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
    2187                 :            : }
    2188                 :            : 
    2189                 :            : /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
    2190                 :            :    return its code, otherwise return IFN_LAST.  Note that this function
    2191                 :            :    only tests whether the function is defined in internals.def, not whether
    2192                 :            :    it is actually available on the target.  */
    2193                 :            : 
    2194                 :            : internal_fn
    2195                 :     363318 : associated_internal_fn (tree fndecl)
    2196                 :            : {
    2197                 :     363318 :   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
    2198                 :     363318 :   tree return_type = TREE_TYPE (TREE_TYPE (fndecl));
    2199                 :     363318 :   switch (DECL_FUNCTION_CODE (fndecl))
    2200                 :            :     {
    2201                 :            : #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2202                 :            :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2203                 :            : #define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
    2204                 :            :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
    2205                 :            :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
    2206                 :            : #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2207                 :            :     CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2208                 :            : #include "internal-fn.def"
    2209                 :            : 
    2210                 :          3 :     CASE_FLT_FN (BUILT_IN_POW10):
    2211                 :          3 :       return IFN_EXP10;
    2212                 :            : 
    2213                 :         33 :     CASE_FLT_FN (BUILT_IN_DREM):
    2214                 :         33 :       return IFN_REMAINDER;
    2215                 :            : 
    2216                 :        551 :     CASE_FLT_FN (BUILT_IN_SCALBN):
    2217                 :        551 :     CASE_FLT_FN (BUILT_IN_SCALBLN):
    2218                 :       1653 :       if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
    2219                 :        551 :         return IFN_LDEXP;
    2220                 :            :       return IFN_LAST;
    2221                 :            : 
    2222                 :     313335 :     default:
    2223                 :     313335 :       return IFN_LAST;
    2224                 :            :     }
    2225                 :            : }
    2226                 :            : 
    2227                 :            : /* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
    2228                 :            :    on the current target by a call to an internal function, return the
    2229                 :            :    code of that internal function, otherwise return IFN_LAST.  The caller
    2230                 :            :    is responsible for ensuring that any side-effects of the built-in
    2231                 :            :    call are dealt with correctly.  E.g. if CALL sets errno, the caller
    2232                 :            :    must decide that the errno result isn't needed or make it available
    2233                 :            :    in some other way.  */
    2234                 :            : 
    2235                 :            : internal_fn
    2236                 :     507062 : replacement_internal_fn (gcall *call)
    2237                 :            : {
    2238                 :     507062 :   if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    2239                 :            :     {
    2240                 :     362897 :       internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
    2241                 :     362897 :       if (ifn != IFN_LAST)
    2242                 :            :         {
    2243                 :      49639 :           tree_pair types = direct_internal_fn_types (ifn, call);
    2244                 :      49639 :           optimization_type opt_type = bb_optimization_type (gimple_bb (call));
    2245                 :      49639 :           if (direct_internal_fn_supported_p (ifn, types, opt_type))
    2246                 :      31306 :             return ifn;
    2247                 :            :         }
    2248                 :            :     }
    2249                 :            :   return IFN_LAST;
    2250                 :            : }
    2251                 :            : 
    2252                 :            : /* Expand a call to the builtin trinary math functions (fma).
    2253                 :            :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2254                 :            :    function in-line.  EXP is the expression that is a call to the builtin
    2255                 :            :    function; if convenient, the result should be placed in TARGET.
    2256                 :            :    SUBTARGET may be used as the target for computing one of EXP's
    2257                 :            :    operands.  */
    2258                 :            : 
    2259                 :            : static rtx
    2260                 :         47 : expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
    2261                 :            : {
    2262                 :         47 :   optab builtin_optab;
    2263                 :         47 :   rtx op0, op1, op2, result;
    2264                 :         47 :   rtx_insn *insns;
    2265                 :         47 :   tree fndecl = get_callee_fndecl (exp);
    2266                 :         47 :   tree arg0, arg1, arg2;
    2267                 :         47 :   machine_mode mode;
    2268                 :            : 
    2269                 :         47 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    2270                 :            :     return NULL_RTX;
    2271                 :            : 
    2272                 :         47 :   arg0 = CALL_EXPR_ARG (exp, 0);
    2273                 :         47 :   arg1 = CALL_EXPR_ARG (exp, 1);
    2274                 :         47 :   arg2 = CALL_EXPR_ARG (exp, 2);
    2275                 :            : 
    2276                 :         47 :   switch (DECL_FUNCTION_CODE (fndecl))
    2277                 :            :     {
    2278                 :         47 :     CASE_FLT_FN (BUILT_IN_FMA):
    2279                 :         47 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    2280                 :         47 :       builtin_optab = fma_optab; break;
    2281                 :          0 :     default:
    2282                 :          0 :       gcc_unreachable ();
    2283                 :            :     }
    2284                 :            : 
    2285                 :            :   /* Make a suitable register to place result in.  */
    2286                 :         47 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2287                 :            : 
    2288                 :            :   /* Before working hard, check whether the instruction is available.  */
    2289                 :         47 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2290                 :            :     return NULL_RTX;
    2291                 :            : 
    2292                 :          0 :   result = gen_reg_rtx (mode);
    2293                 :            : 
    2294                 :            :   /* Always stabilize the argument list.  */
    2295                 :          0 :   CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
    2296                 :          0 :   CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
    2297                 :          0 :   CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
    2298                 :            : 
    2299                 :          0 :   op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
    2300                 :          0 :   op1 = expand_normal (arg1);
    2301                 :          0 :   op2 = expand_normal (arg2);
    2302                 :            : 
    2303                 :          0 :   start_sequence ();
    2304                 :            : 
    2305                 :            :   /* Compute into RESULT.
    2306                 :            :      Set RESULT to wherever the result comes back.  */
    2307                 :          0 :   result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
    2308                 :            :                               result, 0);
    2309                 :            : 
    2310                 :            :   /* If we were unable to expand via the builtin, stop the sequence
    2311                 :            :      (without outputting the insns) and call to the library function
    2312                 :            :      with the stabilized argument list.  */
    2313                 :          0 :   if (result == 0)
    2314                 :            :     {
    2315                 :          0 :       end_sequence ();
    2316                 :          0 :       return expand_call (exp, target, target == const0_rtx);
    2317                 :            :     }
    2318                 :            : 
    2319                 :            :   /* Output the entire sequence.  */
    2320                 :          0 :   insns = get_insns ();
    2321                 :          0 :   end_sequence ();
    2322                 :          0 :   emit_insn (insns);
    2323                 :            : 
    2324                 :          0 :   return result;
    2325                 :            : }
    2326                 :            : 
    2327                 :            : /* Expand a call to the builtin sin and cos math functions.
    2328                 :            :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2329                 :            :    function in-line.  EXP is the expression that is a call to the builtin
    2330                 :            :    function; if convenient, the result should be placed in TARGET.
    2331                 :            :    SUBTARGET may be used as the target for computing one of EXP's
    2332                 :            :    operands.  */
    2333                 :            : 
    2334                 :            : static rtx
    2335                 :         47 : expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
    2336                 :            : {
    2337                 :         47 :   optab builtin_optab;
    2338                 :         47 :   rtx op0;
    2339                 :         47 :   rtx_insn *insns;
    2340                 :         47 :   tree fndecl = get_callee_fndecl (exp);
    2341                 :         47 :   machine_mode mode;
    2342                 :         47 :   tree arg;
    2343                 :            : 
    2344                 :         47 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2345                 :            :     return NULL_RTX;
    2346                 :            : 
    2347                 :         31 :   arg = CALL_EXPR_ARG (exp, 0);
    2348                 :            : 
    2349                 :         31 :   switch (DECL_FUNCTION_CODE (fndecl))
    2350                 :            :     {
    2351                 :         31 :     CASE_FLT_FN (BUILT_IN_SIN):
    2352                 :         31 :     CASE_FLT_FN (BUILT_IN_COS):
    2353                 :         31 :       builtin_optab = sincos_optab; break;
    2354                 :          0 :     default:
    2355                 :          0 :       gcc_unreachable ();
    2356                 :            :     }
    2357                 :            : 
    2358                 :            :   /* Make a suitable register to place result in.  */
    2359                 :         31 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2360                 :            : 
    2361                 :            :   /* Check if sincos insn is available, otherwise fallback
    2362                 :            :      to sin or cos insn.  */
    2363                 :         31 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2364                 :         31 :     switch (DECL_FUNCTION_CODE (fndecl))
    2365                 :            :       {
    2366                 :            :       CASE_FLT_FN (BUILT_IN_SIN):
    2367                 :            :         builtin_optab = sin_optab; break;
    2368                 :         14 :       CASE_FLT_FN (BUILT_IN_COS):
    2369                 :         14 :         builtin_optab = cos_optab; break;
    2370                 :          0 :       default:
    2371                 :          0 :         gcc_unreachable ();
    2372                 :            :       }
    2373                 :            : 
    2374                 :            :   /* Before working hard, check whether the instruction is available.  */
    2375                 :         31 :   if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
    2376                 :            :     {
    2377                 :          0 :       rtx result = gen_reg_rtx (mode);
    2378                 :            : 
    2379                 :            :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2380                 :            :          need to expand the argument again.  This way, we will not perform
    2381                 :            :          side-effects more the once.  */
    2382                 :          0 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2383                 :            : 
    2384                 :          0 :       op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    2385                 :            : 
    2386                 :          0 :       start_sequence ();
    2387                 :            : 
    2388                 :            :       /* Compute into RESULT.
    2389                 :            :          Set RESULT to wherever the result comes back.  */
    2390                 :          0 :       if (builtin_optab == sincos_optab)
    2391                 :            :         {
    2392                 :          0 :           int ok;
    2393                 :            : 
    2394                 :          0 :           switch (DECL_FUNCTION_CODE (fndecl))
    2395                 :            :             {
    2396                 :          0 :             CASE_FLT_FN (BUILT_IN_SIN):
    2397                 :          0 :               ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
    2398                 :          0 :               break;
    2399                 :          0 :             CASE_FLT_FN (BUILT_IN_COS):
    2400                 :          0 :               ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
    2401                 :          0 :               break;
    2402                 :          0 :             default:
    2403                 :          0 :               gcc_unreachable ();
    2404                 :            :             }
    2405                 :          0 :           gcc_assert (ok);
    2406                 :            :         }
    2407                 :            :       else
    2408                 :          0 :         result = expand_unop (mode, builtin_optab, op0, result, 0);
    2409                 :            : 
    2410                 :          0 :       if (result != 0)
    2411                 :            :         {
    2412                 :            :           /* Output the entire sequence.  */
    2413                 :          0 :           insns = get_insns ();
    2414                 :          0 :           end_sequence ();
    2415                 :          0 :           emit_insn (insns);
    2416                 :          0 :           return result;
    2417                 :            :         }
    2418                 :            : 
    2419                 :            :       /* If we were unable to expand via the builtin, stop the sequence
    2420                 :            :          (without outputting the insns) and call to the library function
    2421                 :            :          with the stabilized argument list.  */
    2422                 :          0 :       end_sequence ();
    2423                 :            :     }
    2424                 :            : 
    2425                 :         31 :   return expand_call (exp, target, target == const0_rtx);
    2426                 :            : }
    2427                 :            : 
    2428                 :            : /* Given an interclass math builtin decl FNDECL and it's argument ARG
    2429                 :            :    return an RTL instruction code that implements the functionality.
    2430                 :            :    If that isn't possible or available return CODE_FOR_nothing.  */
    2431                 :            : 
    2432                 :            : static enum insn_code
    2433                 :      13622 : interclass_mathfn_icode (tree arg, tree fndecl)
    2434                 :            : {
    2435                 :      13622 :   bool errno_set = false;
    2436                 :      13622 :   optab builtin_optab = unknown_optab;
    2437                 :      13622 :   machine_mode mode;
    2438                 :            : 
    2439                 :      13622 :   switch (DECL_FUNCTION_CODE (fndecl))
    2440                 :            :     {
    2441                 :          4 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    2442                 :          4 :       errno_set = true; builtin_optab = ilogb_optab; break;
    2443                 :       4752 :     CASE_FLT_FN (BUILT_IN_ISINF):
    2444                 :       4752 :       builtin_optab = isinf_optab; break;
    2445                 :            :     case BUILT_IN_ISNORMAL:
    2446                 :            :     case BUILT_IN_ISFINITE:
    2447                 :            :     CASE_FLT_FN (BUILT_IN_FINITE):
    2448                 :            :     case BUILT_IN_FINITED32:
    2449                 :            :     case BUILT_IN_FINITED64:
    2450                 :            :     case BUILT_IN_FINITED128:
    2451                 :            :     case BUILT_IN_ISINFD32:
    2452                 :            :     case BUILT_IN_ISINFD64:
    2453                 :            :     case BUILT_IN_ISINFD128:
    2454                 :            :       /* These builtins have no optabs (yet).  */
    2455                 :            :       break;
    2456                 :          0 :     default:
    2457                 :          0 :       gcc_unreachable ();
    2458                 :            :     }
    2459                 :            : 
    2460                 :            :   /* There's no easy way to detect the case we need to set EDOM.  */
    2461                 :      13622 :   if (flag_errno_math && errno_set)
    2462                 :            :     return CODE_FOR_nothing;
    2463                 :            : 
    2464                 :            :   /* Optab mode depends on the mode of the input argument.  */
    2465                 :      13622 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2466                 :            : 
    2467                 :      13622 :   if (builtin_optab)
    2468                 :       4756 :     return optab_handler (builtin_optab, mode);
    2469                 :            :   return CODE_FOR_nothing;
    2470                 :            : }
    2471                 :            : 
    2472                 :            : /* Expand a call to one of the builtin math functions that operate on
    2473                 :            :    floating point argument and output an integer result (ilogb, isinf,
    2474                 :            :    isnan, etc).
    2475                 :            :    Return 0 if a normal call should be emitted rather than expanding the
    2476                 :            :    function in-line.  EXP is the expression that is a call to the builtin
    2477                 :            :    function; if convenient, the result should be placed in TARGET.  */
    2478                 :            : 
    2479                 :            : static rtx
    2480                 :          4 : expand_builtin_interclass_mathfn (tree exp, rtx target)
    2481                 :            : {
    2482                 :          4 :   enum insn_code icode = CODE_FOR_nothing;
    2483                 :          4 :   rtx op0;
    2484                 :          4 :   tree fndecl = get_callee_fndecl (exp);
    2485                 :          4 :   machine_mode mode;
    2486                 :          4 :   tree arg;
    2487                 :            : 
    2488                 :          4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2489                 :            :     return NULL_RTX;
    2490                 :            : 
    2491                 :          4 :   arg = CALL_EXPR_ARG (exp, 0);
    2492                 :          4 :   icode = interclass_mathfn_icode (arg, fndecl);
    2493                 :          4 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2494                 :            : 
    2495                 :          4 :   if (icode != CODE_FOR_nothing)
    2496                 :            :     {
    2497                 :          2 :       class expand_operand ops[1];
    2498                 :          2 :       rtx_insn *last = get_last_insn ();
    2499                 :          2 :       tree orig_arg = arg;
    2500                 :            : 
    2501                 :            :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2502                 :            :          need to expand the argument again.  This way, we will not perform
    2503                 :            :          side-effects more the once.  */
    2504                 :          2 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2505                 :            : 
    2506                 :          2 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2507                 :            : 
    2508                 :          2 :       if (mode != GET_MODE (op0))
    2509                 :          0 :         op0 = convert_to_mode (mode, op0, 0);
    2510                 :            : 
    2511                 :          2 :       create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
    2512                 :          2 :       if (maybe_legitimize_operands (icode, 0, 1, ops)
    2513                 :          2 :           && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
    2514                 :          1 :         return ops[0].value;
    2515                 :            : 
    2516                 :          1 :       delete_insns_since (last);
    2517                 :          1 :       CALL_EXPR_ARG (exp, 0) = orig_arg;
    2518                 :            :     }
    2519                 :            : 
    2520                 :            :   return NULL_RTX;
    2521                 :            : }
    2522                 :            : 
    2523                 :            : /* Expand a call to the builtin sincos math function.
    2524                 :            :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2525                 :            :    function in-line.  EXP is the expression that is a call to the builtin
    2526                 :            :    function.  */
    2527                 :            : 
    2528                 :            : static rtx
    2529                 :          3 : expand_builtin_sincos (tree exp)
    2530                 :            : {
    2531                 :          3 :   rtx op0, op1, op2, target1, target2;
    2532                 :          3 :   machine_mode mode;
    2533                 :          3 :   tree arg, sinp, cosp;
    2534                 :          3 :   int result;
    2535                 :          3 :   location_t loc = EXPR_LOCATION (exp);
    2536                 :          3 :   tree alias_type, alias_off;
    2537                 :            : 
    2538                 :          3 :   if (!validate_arglist (exp, REAL_TYPE,
    2539                 :            :                          POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    2540                 :            :     return NULL_RTX;
    2541                 :            : 
    2542                 :          3 :   arg = CALL_EXPR_ARG (exp, 0);
    2543                 :          3 :   sinp = CALL_EXPR_ARG (exp, 1);
    2544                 :          3 :   cosp = CALL_EXPR_ARG (exp, 2);
    2545                 :            : 
    2546                 :            :   /* Make a suitable register to place result in.  */
    2547                 :          3 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2548                 :            : 
    2549                 :            :   /* Check if sincos insn is available, otherwise emit the call.  */
    2550                 :          3 :   if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
    2551                 :            :     return NULL_RTX;
    2552                 :            : 
    2553                 :          0 :   target1 = gen_reg_rtx (mode);
    2554                 :          0 :   target2 = gen_reg_rtx (mode);
    2555                 :            : 
    2556                 :          0 :   op0 = expand_normal (arg);
    2557                 :          0 :   alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
    2558                 :          0 :   alias_off = build_int_cst (alias_type, 0);
    2559                 :          0 :   op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2560                 :            :                                         sinp, alias_off));
    2561                 :          0 :   op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2562                 :            :                                         cosp, alias_off));
    2563                 :            : 
    2564                 :            :   /* Compute into target1 and target2.
    2565                 :            :      Set TARGET to wherever the result comes back.  */
    2566                 :          0 :   result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
    2567                 :          0 :   gcc_assert (result);
    2568                 :            : 
    2569                 :            :   /* Move target1 and target2 to the memory locations indicated
    2570                 :            :      by op1 and op2.  */
    2571                 :          0 :   emit_move_insn (op1, target1);
    2572                 :          0 :   emit_move_insn (op2, target2);
    2573                 :            : 
    2574                 :          0 :   return const0_rtx;
    2575                 :            : }
    2576                 :            : 
    2577                 :            : /* Expand a call to the internal cexpi builtin to the sincos math function.
    2578                 :            :    EXP is the expression that is a call to the builtin function; if convenient,
    2579                 :            :    the result should be placed in TARGET.  */
    2580                 :            : 
    2581                 :            : static rtx
    2582                 :        145 : expand_builtin_cexpi (tree exp, rtx target)
    2583                 :            : {
    2584                 :        145 :   tree fndecl = get_callee_fndecl (exp);
    2585                 :        145 :   tree arg, type;
    2586                 :        145 :   machine_mode mode;
    2587                 :        145 :   rtx op0, op1, op2;
    2588                 :        145 :   location_t loc = EXPR_LOCATION (exp);
    2589                 :            : 
    2590                 :        145 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2591                 :            :     return NULL_RTX;
    2592                 :            : 
    2593                 :        145 :   arg = CALL_EXPR_ARG (exp, 0);
    2594                 :        145 :   type = TREE_TYPE (arg);
    2595                 :        145 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2596                 :            : 
    2597                 :            :   /* Try expanding via a sincos optab, fall back to emitting a libcall
    2598                 :            :      to sincos or cexp.  We are sure we have sincos or cexp because cexpi
    2599                 :            :      is only generated from sincos, cexp or if we have either of them.  */
    2600                 :        145 :   if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
    2601                 :            :     {
    2602                 :          6 :       op1 = gen_reg_rtx (mode);
    2603                 :          6 :       op2 = gen_reg_rtx (mode);
    2604                 :            : 
    2605                 :          6 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2606                 :            : 
    2607                 :            :       /* Compute into op1 and op2.  */
    2608                 :          6 :       expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
    2609                 :            :     }
    2610                 :        139 :   else if (targetm.libc_has_function (function_sincos))
    2611                 :            :     {
    2612                 :        139 :       tree call, fn = NULL_TREE;
    2613                 :        139 :       tree top1, top2;
    2614                 :        139 :       rtx op1a, op2a;
    2615                 :            : 
    2616                 :        139 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2617                 :         41 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
    2618                 :         98 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2619                 :         81 :         fn = builtin_decl_explicit (BUILT_IN_SINCOS);
    2620                 :         17 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2621                 :         17 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
    2622                 :            :       else
    2623                 :          0 :         gcc_unreachable ();
    2624                 :            : 
    2625                 :        139 :       op1 = assign_temp (TREE_TYPE (arg), 1, 1);
    2626                 :        139 :       op2 = assign_temp (TREE_TYPE (arg), 1, 1);
    2627                 :        139 :       op1a = copy_addr_to_reg (XEXP (op1, 0));
    2628                 :        139 :       op2a = copy_addr_to_reg (XEXP (op2, 0));
    2629                 :        139 :       top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
    2630                 :        139 :       top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
    2631                 :            : 
    2632                 :            :       /* Make sure not to fold the sincos call again.  */
    2633                 :        139 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2634                 :        139 :       expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
    2635                 :            :                                       call, 3, arg, top1, top2));
    2636                 :            :     }
    2637                 :            :   else
    2638                 :            :     {
    2639                 :          0 :       tree call, fn = NULL_TREE, narg;
    2640                 :          0 :       tree ctype = build_complex_type (type);
    2641                 :            : 
    2642                 :          0 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2643                 :          0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPF);
    2644                 :          0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2645                 :          0 :         fn = builtin_decl_explicit (BUILT_IN_CEXP);
    2646                 :          0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2647                 :          0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPL);
    2648                 :            :       else
    2649                 :          0 :         gcc_unreachable ();
    2650                 :            : 
    2651                 :            :       /* If we don't have a decl for cexp create one.  This is the
    2652                 :            :          friendliest fallback if the user calls __builtin_cexpi
    2653                 :            :          without full target C99 function support.  */
    2654                 :          0 :       if (fn == NULL_TREE)
    2655                 :            :         {
    2656                 :          0 :           tree fntype;
    2657                 :          0 :           const char *name = NULL;
    2658                 :            : 
    2659                 :          0 :           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2660                 :            :             name = "cexpf";
    2661                 :          0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2662                 :            :             name = "cexp";
    2663                 :          0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2664                 :          0 :             name = "cexpl";
    2665                 :            : 
    2666                 :          0 :           fntype = build_function_type_list (ctype, ctype, NULL_TREE);
    2667                 :          0 :           fn = build_fn_decl (name, fntype);
    2668                 :            :         }
    2669                 :            : 
    2670                 :          0 :       narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
    2671                 :            :                           build_real (type, dconst0), arg);
    2672                 :            : 
    2673                 :            :       /* Make sure not to fold the cexp call again.  */
    2674                 :          0 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2675                 :          0 :       return expand_expr (build_call_nary (ctype, call, 1, narg),
    2676                 :          0 :                           target, VOIDmode, EXPAND_NORMAL);
    2677                 :            :     }
    2678                 :            : 
    2679                 :            :   /* Now build the proper return type.  */
    2680                 :        435 :   return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
    2681                 :        145 :                               make_tree (TREE_TYPE (arg), op2),
    2682                 :        145 :                               make_tree (TREE_TYPE (arg), op1)),
    2683                 :        145 :                       target, VOIDmode, EXPAND_NORMAL);
    2684                 :            : }
    2685                 :            : 
    2686                 :            : /* Conveniently construct a function call expression.  FNDECL names the
    2687                 :            :    function to be called, N is the number of arguments, and the "..."
    2688                 :            :    parameters are the argument expressions.  Unlike build_call_exr
    2689                 :            :    this doesn't fold the call, hence it will always return a CALL_EXPR.  */
    2690                 :            : 
    2691                 :            : static tree
    2692                 :       5721 : build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
    2693                 :            : {
    2694                 :       5721 :   va_list ap;
    2695                 :       5721 :   tree fntype = TREE_TYPE (fndecl);
    2696                 :       5721 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
    2697                 :            : 
    2698                 :       5721 :   va_start (ap, n);
    2699                 :       5721 :   fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
    2700                 :       5721 :   va_end (ap);
    2701                 :       5721 :   SET_EXPR_LOCATION (fn, loc);
    2702                 :       5721 :   return fn;
    2703                 :            : }
    2704                 :            : 
    2705                 :            : /* Expand a call to one of the builtin rounding functions gcc defines
    2706                 :            :    as an extension (lfloor and lceil).  As these are gcc extensions we
    2707                 :            :    do not need to worry about setting errno to EDOM.
    2708                 :            :    If expanding via optab fails, lower expression to (int)(floor(x)).
    2709                 :            :    EXP is the expression that is a call to the builtin function;
    2710                 :            :    if convenient, the result should be placed in TARGET.  */
    2711                 :            : 
    2712                 :            : static rtx
    2713                 :        327 : expand_builtin_int_roundingfn (tree exp, rtx target)
    2714                 :            : {
    2715                 :        327 :   convert_optab builtin_optab;
    2716                 :        327 :   rtx op0, tmp;
    2717                 :        327 :   rtx_insn *insns;
    2718                 :        327 :   tree fndecl = get_callee_fndecl (exp);
    2719                 :        327 :   enum built_in_function fallback_fn;
    2720                 :        327 :   tree fallback_fndecl;
    2721                 :        327 :   machine_mode mode;
    2722                 :        327 :   tree arg;
    2723                 :            : 
    2724                 :        327 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2725                 :            :     return NULL_RTX;
    2726                 :            : 
    2727                 :        327 :   arg = CALL_EXPR_ARG (exp, 0);
    2728                 :            : 
    2729                 :        327 :   switch (DECL_FUNCTION_CODE (fndecl))
    2730                 :            :     {
    2731                 :            :     CASE_FLT_FN (BUILT_IN_ICEIL):
    2732                 :            :     CASE_FLT_FN (BUILT_IN_LCEIL):
    2733                 :            :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    2734                 :            :       builtin_optab = lceil_optab;
    2735                 :            :       fallback_fn = BUILT_IN_CEIL;
    2736                 :            :       break;
    2737                 :            : 
    2738                 :        164 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    2739                 :        164 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    2740                 :        164 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    2741                 :        164 :       builtin_optab = lfloor_optab;
    2742                 :        164 :       fallback_fn = BUILT_IN_FLOOR;
    2743                 :        164 :       break;
    2744                 :            : 
    2745                 :          0 :     default:
    2746                 :          0 :       gcc_unreachable ();
    2747                 :            :     }
    2748                 :            : 
    2749                 :            :   /* Make a suitable register to place result in.  */
    2750                 :        327 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2751                 :            : 
    2752                 :        327 :   target = gen_reg_rtx (mode);
    2753                 :            : 
    2754                 :            :   /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2755                 :            :      need to expand the argument again.  This way, we will not perform
    2756                 :            :      side-effects more the once.  */
    2757                 :        327 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2758                 :            : 
    2759                 :        327 :   op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    2760                 :            : 
    2761                 :        327 :   start_sequence ();
    2762                 :            : 
    2763                 :            :   /* Compute into TARGET.  */
    2764                 :        327 :   if (expand_sfix_optab (target, op0, builtin_optab))
    2765                 :            :     {
    2766                 :            :       /* Output the entire sequence.  */
    2767                 :        136 :       insns = get_insns ();
    2768                 :        136 :       end_sequence ();
    2769                 :        136 :       emit_insn (insns);
    2770                 :        136 :       return target;
    2771                 :            :     }
    2772                 :            : 
    2773                 :            :   /* If we were unable to expand via the builtin, stop the sequence
    2774                 :            :      (without outputting the insns).  */
    2775                 :        191 :   end_sequence ();
    2776                 :            : 
    2777                 :            :   /* Fall back to floating point rounding optab.  */
    2778                 :        191 :   fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
    2779                 :            : 
    2780                 :            :   /* For non-C99 targets we may end up without a fallback fndecl here
    2781                 :            :      if the user called __builtin_lfloor directly.  In this case emit
    2782                 :            :      a call to the floor/ceil variants nevertheless.  This should result
    2783                 :            :      in the best user experience for not full C99 targets.  */
    2784                 :        191 :   if (fallback_fndecl == NULL_TREE)
    2785                 :            :     {
    2786                 :          0 :       tree fntype;
    2787                 :          0 :       const char *name = NULL;
    2788                 :            : 
    2789                 :          0 :       switch (DECL_FUNCTION_CODE (fndecl))
    2790                 :            :         {
    2791                 :            :         case BUILT_IN_ICEIL:
    2792                 :            :         case BUILT_IN_LCEIL:
    2793                 :            :         case BUILT_IN_LLCEIL:
    2794                 :            :           name = "ceil";
    2795                 :            :           break;
    2796                 :          0 :         case BUILT_IN_ICEILF:
    2797                 :          0 :         case BUILT_IN_LCEILF:
    2798                 :          0 :         case BUILT_IN_LLCEILF:
    2799                 :          0 :           name = "ceilf";
    2800                 :          0 :           break;
    2801                 :          0 :         case BUILT_IN_ICEILL:
    2802                 :          0 :         case BUILT_IN_LCEILL:
    2803                 :          0 :         case BUILT_IN_LLCEILL:
    2804                 :          0 :           name = "ceill";
    2805                 :          0 :           break;
    2806                 :          0 :         case BUILT_IN_IFLOOR:
    2807                 :          0 :         case BUILT_IN_LFLOOR:
    2808                 :          0 :         case BUILT_IN_LLFLOOR:
    2809                 :          0 :           name = "floor";
    2810                 :          0 :           break;
    2811                 :          0 :         case BUILT_IN_IFLOORF:
    2812                 :          0 :         case BUILT_IN_LFLOORF:
    2813                 :          0 :         case BUILT_IN_LLFLOORF:
    2814                 :          0 :           name = "floorf";
    2815                 :          0 :           break;
    2816                 :          0 :         case BUILT_IN_IFLOORL:
    2817                 :          0 :         case BUILT_IN_LFLOORL:
    2818                 :          0 :         case BUILT_IN_LLFLOORL:
    2819                 :          0 :           name = "floorl";
    2820                 :          0 :           break;
    2821                 :          0 :         default:
    2822                 :          0 :           gcc_unreachable ();
    2823                 :            :         }
    2824                 :            : 
    2825                 :          0 :       fntype = build_function_type_list (TREE_TYPE (arg),
    2826                 :          0 :                                          TREE_TYPE (arg), NULL_TREE);
    2827                 :          0 :       fallback_fndecl = build_fn_decl (name, fntype);
    2828                 :            :     }
    2829                 :            : 
    2830                 :        191 :   exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
    2831                 :            : 
    2832                 :        191 :   tmp = expand_normal (exp);
    2833                 :        191 :   tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
    2834                 :            : 
    2835                 :            :   /* Truncate the result of floating point optab to integer
    2836                 :            :      via expand_fix ().  */
    2837                 :        191 :   target = gen_reg_rtx (mode);
    2838                 :        191 :   expand_fix (target, tmp, 0);
    2839                 :            : 
    2840                 :        191 :   return target;
    2841                 :            : }
    2842                 :            : 
    2843                 :            : /* Expand a call to one of the builtin math functions doing integer
    2844                 :            :    conversion (lrint).
    2845                 :            :    Return 0 if a normal call should be emitted rather than expanding the
    2846                 :            :    function in-line.  EXP is the expression that is a call to the builtin
    2847                 :            :    function; if convenient, the result should be placed in TARGET.  */
    2848                 :            : 
    2849                 :            : static rtx
    2850                 :        566 : expand_builtin_int_roundingfn_2 (tree exp, rtx target)
    2851                 :            : {
    2852                 :        566 :   convert_optab builtin_optab;
    2853                 :        566 :   rtx op0;
    2854                 :        566 :   rtx_insn *insns;
    2855                 :        566 :   tree fndecl = get_callee_fndecl (exp);
    2856                 :        566 :   tree arg;
    2857                 :        566 :   machine_mode mode;
    2858                 :        566 :   enum built_in_function fallback_fn = BUILT_IN_NONE;
    2859                 :            : 
    2860                 :        566 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2861                 :            :     return NULL_RTX;
    2862                 :            : 
    2863                 :        466 :   arg = CALL_EXPR_ARG (exp, 0);
    2864                 :            : 
    2865                 :        466 :   switch (DECL_FUNCTION_CODE (fndecl))
    2866                 :            :     {
    2867                 :         17 :     CASE_FLT_FN (BUILT_IN_IRINT):
    2868                 :         17 :       fallback_fn = BUILT_IN_LRINT;
    2869                 :            :       gcc_fallthrough ();
    2870                 :            :     CASE_FLT_FN (BUILT_IN_LRINT):
    2871                 :            :     CASE_FLT_FN (BUILT_IN_LLRINT):
    2872                 :            :       builtin_optab = lrint_optab;
    2873                 :            :       break;
    2874                 :            : 
    2875                 :         75 :     CASE_FLT_FN (BUILT_IN_IROUND):
    2876                 :         75 :       fallback_fn = BUILT_IN_LROUND;
    2877                 :            :       gcc_fallthrough ();
    2878                 :            :     CASE_FLT_FN (BUILT_IN_LROUND):
    2879                 :            :     CASE_FLT_FN (BUILT_IN_LLROUND):
    2880                 :            :       builtin_optab = lround_optab;
    2881                 :            :       break;
    2882                 :            : 
    2883                 :          0 :     default:
    2884                 :          0 :       gcc_unreachable ();
    2885                 :            :     }
    2886                 :            : 
    2887                 :            :   /* There's no easy way to detect the case we need to set EDOM.  */
    2888                 :        466 :   if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
    2889                 :            :     return NULL_RTX;
    2890                 :            : 
    2891                 :            :   /* Make a suitable register to place result in.  */
    2892                 :        280 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2893                 :            : 
    2894                 :            :   /* There's no easy way to detect the case we need to set EDOM.  */
    2895                 :        280 :   if (!flag_errno_math)
    2896                 :            :     {
    2897                 :        280 :       rtx result = gen_reg_rtx (mode);
    2898                 :            : 
    2899                 :            :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2900                 :            :          need to expand the argument again.  This way, we will not perform
    2901                 :            :          side-effects more the once.  */
    2902                 :        280 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2903                 :            : 
    2904                 :        280 :       op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    2905                 :            : 
    2906                 :        280 :       start_sequence ();
    2907                 :            : 
    2908                 :        280 :       if (expand_sfix_optab (result, op0, builtin_optab))
    2909                 :            :         {
    2910                 :            :           /* Output the entire sequence.  */
    2911                 :        212 :           insns = get_insns ();
    2912                 :        212 :           end_sequence ();
    2913                 :        212 :           emit_insn (insns);
    2914                 :        212 :           return result;
    2915                 :            :         }
    2916                 :            : 
    2917                 :            :       /* If we were unable to expand via the builtin, stop the sequence
    2918                 :            :          (without outputting the insns) and call to the library function
    2919                 :            :          with the stabilized argument list.  */
    2920                 :         68 :       end_sequence ();
    2921                 :            :     }
    2922                 :            : 
    2923                 :         68 :   if (fallback_fn != BUILT_IN_NONE)
    2924                 :            :     {
    2925                 :            :       /* Fall back to rounding to long int.  Use implicit_p 0 - for non-C99
    2926                 :            :          targets, (int) round (x) should never be transformed into
    2927                 :            :          BUILT_IN_IROUND and if __builtin_iround is called directly, emit
    2928                 :            :          a call to lround in the hope that the target provides at least some
    2929                 :            :          C99 functions.  This should result in the best user experience for
    2930                 :            :          not full C99 targets.  */
    2931                 :         54 :       tree fallback_fndecl = mathfn_built_in_1
    2932                 :         54 :         (TREE_TYPE (arg), as_combined_fn (fallback_fn), 0);
    2933                 :            : 
    2934                 :         54 :       exp = build_call_nofold_loc (EXPR_LOCATION (exp),
    2935                 :            :                                    fallback_fndecl, 1, arg);
    2936                 :            : 
    2937                 :         54 :       target = expand_call (exp, NULL_RTX, target == const0_rtx);
    2938                 :         54 :       target = maybe_emit_group_store (target, TREE_TYPE (exp));
    2939                 :         54 :       return convert_to_mode (mode, target, 0);
    2940                 :            :     }
    2941                 :            : 
    2942                 :         14 :   return expand_call (exp, target, target == const0_rtx);
    2943                 :            : }
    2944                 :            : 
    2945                 :            : /* Expand a call to the powi built-in mathematical function.  Return NULL_RTX if
    2946                 :            :    a normal call should be emitted rather than expanding the function
    2947                 :            :    in-line.  EXP is the expression that is a call to the builtin
    2948                 :            :    function; if convenient, the result should be placed in TARGET.  */
    2949                 :            : 
    2950                 :            : static rtx
    2951                 :        313 : expand_builtin_powi (tree exp, rtx target)
    2952                 :            : {
    2953                 :        313 :   tree arg0, arg1;
    2954                 :        313 :   rtx op0, op1;
    2955                 :        313 :   machine_mode mode;
    2956                 :        313 :   machine_mode mode2;
    2957                 :            : 
    2958                 :        313 :   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
    2959                 :            :     return NULL_RTX;
    2960                 :            : 
    2961                 :        313 :   arg0 = CALL_EXPR_ARG (exp, 0);
    2962                 :        313 :   arg1 = CALL_EXPR_ARG (exp, 1);
    2963                 :        313 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2964                 :            : 
    2965                 :            :   /* Emit a libcall to libgcc.  */
    2966                 :            : 
    2967                 :            :   /* Mode of the 2nd argument must match that of an int.  */
    2968                 :        626 :   mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
    2969                 :            : 
    2970                 :        313 :   if (target == NULL_RTX)
    2971                 :          0 :     target = gen_reg_rtx (mode);
    2972                 :            : 
    2973                 :        313 :   op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    2974                 :        313 :   if (GET_MODE (op0) != mode)
    2975                 :          0 :     op0 = convert_to_mode (mode, op0, 0);
    2976                 :        313 :   op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
    2977                 :        313 :   if (GET_MODE (op1) != mode2)
    2978                 :         39 :     op1 = convert_to_mode (mode2, op1, 0);
    2979                 :            : 
    2980                 :        313 :   target = emit_library_call_value (optab_libfunc (powi_optab, mode),
    2981                 :            :                                     target, LCT_CONST, mode,
    2982                 :            :                                     op0, mode, op1, mode2);
    2983                 :            : 
    2984                 :        313 :   return target;
    2985                 :            : }
    2986                 :            : 
    2987                 :            : /* Expand expression EXP which is a call to the strlen builtin.  Return
    2988                 :            :    NULL_RTX if we failed and the caller should emit a normal call, otherwise
    2989                 :            :    try to get the result in TARGET, if convenient.  */
    2990                 :            : 
    2991                 :            : static rtx
    2992                 :       9551 : expand_builtin_strlen (tree exp, rtx target,
    2993                 :            :                        machine_mode target_mode)
    2994                 :            : {
    2995                 :       9551 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    2996                 :            :     return NULL_RTX;
    2997                 :            : 
    2998                 :       9526 :   class expand_operand ops[4];
    2999                 :       9526 :   rtx pat;
    3000                 :       9526 :   tree len;
    3001                 :       9526 :   tree src = CALL_EXPR_ARG (exp, 0);
    3002                 :       9526 :   rtx src_reg;
    3003                 :       9526 :   rtx_insn *before_strlen;
    3004                 :       9526 :   machine_mode insn_mode;
    3005                 :       9526 :   enum insn_code icode = CODE_FOR_nothing;
    3006                 :       9526 :   unsigned int align;
    3007                 :            : 
    3008                 :            :   /* If the length can be computed at compile-time, return it.  */
    3009                 :       9526 :   len = c_strlen (src, 0);
    3010                 :       9526 :   if (len)
    3011                 :         12 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3012                 :            : 
    3013                 :            :   /* If the length can be computed at compile-time and is constant
    3014                 :            :      integer, but there are side-effects in src, evaluate
    3015                 :            :      src for side-effects, then return len.
    3016                 :            :      E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
    3017                 :            :      can be optimized into: i++; x = 3;  */
    3018                 :       9514 :   len = c_strlen (src, 1);
    3019                 :       9514 :   if (len && TREE_CODE (len) == INTEGER_CST)
    3020                 :            :     {
    3021                 :          0 :       expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
    3022                 :          0 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3023                 :            :     }
    3024                 :            : 
    3025                 :       9514 :   align = get_pointer_alignment (src) / BITS_PER_UNIT;
    3026                 :            : 
    3027                 :            :   /* If SRC is not a pointer type, don't do this operation inline.  */
    3028                 :       9514 :   if (align == 0)
    3029                 :            :     return NULL_RTX;
    3030                 :            : 
    3031                 :            :   /* Bail out if we can't compute strlen in the right mode.  */
    3032                 :       9514 :   FOR_EACH_MODE_FROM (insn_mode, target_mode)
    3033                 :            :     {
    3034                 :       9514 :       icode = optab_handler (strlen_optab, insn_mode);
    3035                 :       9514 :       if (icode != CODE_FOR_nothing)
    3036                 :            :         break;
    3037                 :            :     }
    3038                 :       9514 :   if (insn_mode == VOIDmode)
    3039                 :            :     return NULL_RTX;
    3040                 :            : 
    3041                 :            :   /* Make a place to hold the source address.  We will not expand
    3042                 :            :      the actual source until we are sure that the expansion will
    3043                 :            :      not fail -- there are trees that cannot be expanded twice.  */
    3044                 :       9917 :   src_reg = gen_reg_rtx (Pmode);
    3045                 :            : 
    3046                 :            :   /* Mark the beginning of the strlen sequence so we can emit the
    3047                 :            :      source operand later.  */
    3048                 :       9514 :   before_strlen = get_last_insn ();
    3049                 :            : 
    3050                 :       9514 :   create_output_operand (&ops[0], target, insn_mode);
    3051                 :       9514 :   create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
    3052                 :       9514 :   create_integer_operand (&ops[2], 0);
    3053                 :       9514 :   create_integer_operand (&ops[3], align);
    3054                 :       9514 :   if (!maybe_expand_insn (icode, 4, ops))
    3055                 :            :     return NULL_RTX;
    3056                 :            : 
    3057                 :            :   /* Check to see if the argument was declared attribute nonstring
    3058                 :            :      and if so, issue a warning since at this point it's not known
    3059                 :            :      to be nul-terminated.  */
    3060                 :         10 :   maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    3061                 :            : 
    3062                 :            :   /* Now that we are assured of success, expand the source.  */
    3063                 :         10 :   start_sequence ();
    3064                 :         14 :   pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
    3065                 :         10 :   if (pat != src_reg)
    3066                 :            :     {
    3067                 :            : #ifdef POINTERS_EXTEND_UNSIGNED
    3068                 :         14 :       if (GET_MODE (pat) != Pmode)
    3069                 :          0 :         pat = convert_to_mode (Pmode, pat,
    3070                 :            :                                POINTERS_EXTEND_UNSIGNED);
    3071                 :            : #endif
    3072                 :         10 :       emit_move_insn (src_reg, pat);
    3073                 :            :     }
    3074                 :         10 :   pat = get_insns ();
    3075                 :         10 :   end_sequence ();
    3076                 :            : 
    3077                 :         10 :   if (before_strlen)
    3078                 :         10 :     emit_insn_after (pat, before_strlen);
    3079                 :            :   else
    3080                 :          0 :     emit_insn_before (pat, get_insns ());
    3081                 :            : 
    3082                 :            :   /* Return the value in the proper mode for this function.  */
    3083                 :         10 :   if (GET_MODE (ops[0].value) == target_mode)
    3084                 :            :     target = ops[0].value;
    3085                 :          0 :   else if (target != 0)
    3086                 :          0 :     convert_move (target, ops[0].value, 0);
    3087                 :            :   else
    3088                 :          0 :     target = convert_to_mode (target_mode, ops[0].value, 0);
    3089                 :            : 
    3090                 :            :   return target;
    3091                 :            : }
    3092                 :            : 
    3093                 :            : /* Expand call EXP to the strnlen built-in, returning the result
    3094                 :            :    and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    3095                 :            : 
    3096                 :            : static rtx
    3097                 :        455 : expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
    3098                 :            : {
    3099                 :        455 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3100                 :            :     return NULL_RTX;
    3101                 :            : 
    3102                 :        447 :   tree src = CALL_EXPR_ARG (exp, 0);
    3103                 :        447 :   tree bound = CALL_EXPR_ARG (exp, 1);
    3104                 :            : 
    3105                 :        447 :   if (!bound)
    3106                 :            :     return NULL_RTX;
    3107                 :            : 
    3108                 :        447 :   location_t loc = UNKNOWN_LOCATION;
    3109                 :        447 :   if (EXPR_HAS_LOCATION (exp))
    3110                 :        447 :     loc = EXPR_LOCATION (exp);
    3111                 :            : 
    3112                 :        447 :   tree maxobjsize = max_object_size ();
    3113                 :        447 :   tree func = get_callee_fndecl (exp);
    3114                 :            : 
    3115                 :            :   /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
    3116                 :            :      so these conversions aren't necessary.  */
    3117                 :        447 :   c_strlen_data lendata = { };
    3118                 :        447 :   tree len = c_strlen (src, 0, &lendata, 1);
    3119                 :        447 :   if (len)
    3120                 :        102 :     len = fold_convert_loc (loc, TREE_TYPE (bound), len);
    3121                 :            : 
    3122                 :        447 :   if (TREE_CODE (bound) == INTEGER_CST)
    3123                 :            :     {
    3124                 :        297 :       if (!TREE_NO_WARNING (exp)
    3125                 :        297 :           && tree_int_cst_lt (maxobjsize, bound)
    3126                 :        317 :           && warning_at (loc, OPT_Wstringop_overflow_,
    3127                 :            :                          "%K%qD specified bound %E "
    3128                 :            :                          "exceeds maximum object size %E",
    3129                 :            :                          exp, func, bound, maxobjsize))
    3130                 :          9 :         TREE_NO_WARNING (exp) = true;
    3131                 :            : 
    3132                 :        297 :       bool exact = true;
    3133                 :        297 :       if (!len || TREE_CODE (len) != INTEGER_CST)
    3134                 :            :         {
    3135                 :            :           /* Clear EXACT if LEN may be less than SRC suggests,
    3136                 :            :              such as in
    3137                 :            :                strnlen (&a[i], sizeof a)
    3138                 :            :              where the value of i is unknown.  Unless i's value is
    3139                 :            :              zero, the call is unsafe because the bound is greater. */
    3140                 :        258 :           lendata.decl = unterminated_array (src, &len, &exact);
    3141                 :        258 :           if (!lendata.decl)
    3142                 :            :             return NULL_RTX;
    3143                 :            :         }
    3144                 :            : 
    3145                 :        162 :       if (lendata.decl && (tree_int_cst_lt (len, bound) || !exact))
    3146                 :            :         {
    3147                 :         94 :           location_t warnloc
    3148                 :         94 :             = expansion_point_location_if_in_system_header (loc);
    3149                 :            : 
    3150                 :         94 :           if (!TREE_NO_WARNING (exp)
    3151                 :        122 :               && warning_at (warnloc, OPT_Wstringop_overflow_,
    3152                 :            :                              exact
    3153                 :            :                              ? G_("%K%qD specified bound %E exceeds the size "
    3154                 :            :                                   "%E of unterminated array")
    3155                 :            :                              : G_("%K%qD specified bound %E may exceed the "
    3156                 :            :                                   "size of at most %E of unterminated array"),
    3157                 :            :                              exp, func, bound, len))
    3158                 :            :             {
    3159                 :         93 :               inform (DECL_SOURCE_LOCATION (lendata.decl),
    3160                 :            :                       "referenced argument declared here");
    3161                 :         93 :               TREE_NO_WARNING (exp) = true;
    3162                 :            :             }
    3163                 :         94 :           return NULL_RTX;
    3164                 :            :         }
    3165                 :            : 
    3166                 :         68 :       if (!len)
    3167                 :            :         return NULL_RTX;
    3168                 :            : 
    3169                 :         68 :       len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
    3170                 :         68 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3171                 :            :     }
    3172                 :            : 
    3173                 :        150 :   if (TREE_CODE (bound) != SSA_NAME)
    3174                 :            :     return NULL_RTX;
    3175                 :            : 
    3176                 :        150 :   wide_int min, max;
    3177                 :        150 :   enum value_range_kind rng = get_range_info (bound, &min, &max);
    3178                 :        150 :   if (rng != VR_RANGE)
    3179                 :            :     return NULL_RTX;
    3180                 :            : 
    3181                 :         79 :   if (!TREE_NO_WARNING (exp)
    3182                 :         79 :       && wi::ltu_p (wi::to_wide (maxobjsize, min.get_precision ()), min)
    3183                 :         89 :       && warning_at (loc, OPT_Wstringop_overflow_,
    3184                 :            :                      "%K%qD specified bound [%wu, %wu] "
    3185                 :            :                      "exceeds maximum object size %E",
    3186                 :            :                      exp, func, min.to_uhwi (), max.to_uhwi (), maxobjsize))
    3187                 :          5 :     TREE_NO_WARNING (exp) = true;
    3188                 :            : 
    3189                 :         79 :   bool exact = true;
    3190                 :         79 :   if (!len || TREE_CODE (len) != INTEGER_CST)
    3191                 :            :     {
    3192                 :         42 :       lendata.decl = unterminated_array (src, &len, &exact);
    3193                 :         42 :       if (!lendata.decl)
    3194                 :            :         return NULL_RTX;
    3195                 :            :     }
    3196                 :            : 
    3197                 :         56 :   if (lendata.decl
    3198                 :         19 :       && !TREE_NO_WARNING (exp)
    3199                 :         83 :       && (wi::ltu_p (wi::to_wide (len), min)
    3200                 :          8 :           || !exact))
    3201                 :            :     {
    3202                 :         12 :       location_t warnloc
    3203                 :         12 :         = expansion_point_location_if_in_system_header (loc);
    3204                 :            : 
    3205                 :         42 :       if (warning_at (warnloc, OPT_Wstringop_overflow_,
    3206                 :            :                       exact
    3207                 :            :                       ? G_("%K%qD specified bound [%wu, %wu] exceeds "
    3208                 :            :                            "the size %E of unterminated array")
    3209                 :            :                       : G_("%K%qD specified bound [%wu, %wu] may exceed "
    3210                 :            :                            "the size of at most %E of unterminated array"),
    3211                 :            :                       exp, func, min.to_uhwi (), max.to_uhwi (), len))
    3212                 :            :         {
    3213                 :         12 :           inform (DECL_SOURCE_LOCATION (lendata.decl),
    3214                 :            :                   "referenced argument declared here");
    3215                 :         12 :           TREE_NO_WARNING (exp) = true;
    3216                 :            :         }
    3217                 :            :     }
    3218                 :            : 
    3219                 :         56 :   if (lendata.decl)
    3220                 :            :     return NULL_RTX;
    3221                 :            : 
    3222                 :         37 :   if (wi::gtu_p (min, wi::to_wide (len)))
    3223                 :          7 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3224                 :            : 
    3225                 :         30 :   len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
    3226                 :         30 :   return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3227                 :            : }
    3228                 :            : 
    3229                 :            : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    3230                 :            :    bytes from constant string DATA + OFFSET and return it as target
    3231                 :            :    constant.  */
    3232                 :            : 
    3233                 :            : static rtx
    3234                 :      34493 : builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
    3235                 :            :                          scalar_int_mode mode)
    3236                 :            : {
    3237                 :      34493 :   const char *str = (const char *) data;
    3238                 :            : 
    3239                 :      68986 :   gcc_assert (offset >= 0
    3240                 :            :               && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
    3241                 :            :                   <= strlen (str) + 1));
    3242                 :            : 
    3243                 :      34493 :   return c_readstr (str + offset, mode);
    3244                 :            : }
    3245                 :            : 
    3246                 :            : /* LEN specify length of the block of memcpy/memset operation.
    3247                 :            :    Figure out its range and put it into MIN_SIZE/MAX_SIZE. 
    3248                 :            :    In some cases we can make very likely guess on max size, then we
    3249                 :            :    set it into PROBABLE_MAX_SIZE.  */
    3250                 :            : 
    3251                 :            : static void
    3252                 :      76955 : determine_block_size (tree len, rtx len_rtx,
    3253                 :            :                       unsigned HOST_WIDE_INT *min_size,
    3254                 :            :                       unsigned HOST_WIDE_INT *max_size,
    3255                 :            :                       unsigned HOST_WIDE_INT *probable_max_size)
    3256                 :            : {
    3257                 :      76955 :   if (CONST_INT_P (len_rtx))
    3258                 :            :     {
    3259                 :      37954 :       *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
    3260                 :      37954 :       return;
    3261                 :            :     }
    3262                 :            :   else
    3263                 :            :     {
    3264                 :      39001 :       wide_int min, max;
    3265                 :      39001 :       enum value_range_kind range_type = VR_UNDEFINED;
    3266                 :            : 
    3267                 :            :       /* Determine bounds from the type.  */
    3268                 :      39001 :       if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
    3269                 :      39001 :         *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
    3270                 :            :       else
    3271                 :          0 :         *min_size = 0;
    3272                 :      39001 :       if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
    3273                 :      39001 :         *probable_max_size = *max_size
    3274                 :      39001 :           = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
    3275                 :            :       else
    3276                 :          0 :         *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
    3277                 :            : 
    3278                 :      39001 :       if (TREE_CODE (len) == SSA_NAME)
    3279                 :      39001 :         range_type = get_range_info (len, &min, &max);
    3280                 :      39001 :       if (range_type == VR_RANGE)
    3281                 :            :         {
    3282                 :      36572 :           if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
    3283                 :       7810 :             *min_size = min.to_uhwi ();
    3284                 :      36572 :           if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
    3285                 :      10884 :             *probable_max_size = *max_size = max.to_uhwi ();
    3286                 :            :         }
    3287                 :      20715 :       else if (range_type == VR_ANTI_RANGE)
    3288                 :            :         {
    3289                 :            :           /* Anti range 0...N lets us to determine minimal size to N+1.  */
    3290                 :       3501 :           if (min == 0)
    3291                 :            :             {
    3292                 :          0 :               if (wi::fits_uhwi_p (max) && max.to_uhwi () + 1 != 0)
    3293                 :          0 :                 *min_size = max.to_uhwi () + 1;
    3294                 :            :             }
    3295                 :            :           /* Code like
    3296                 :            : 
    3297                 :            :              int n;
    3298                 :            :              if (n < 100)
    3299                 :            :                memcpy (a, b, n)
    3300                 :            : 
    3301                 :            :              Produce anti range allowing negative values of N.  We still
    3302                 :            :              can use the information and make a guess that N is not negative.
    3303                 :            :              */
    3304                 :       3501 :           else if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
    3305                 :       6934 :             *probable_max_size = min.to_uhwi () - 1;
    3306                 :            :         }
    3307                 :            :     }
    3308                 :      39001 :   gcc_checking_assert (*max_size <=
    3309                 :            :                        (unsigned HOST_WIDE_INT)
    3310                 :            :                           GET_MODE_MASK (GET_MODE (len_rtx)));
    3311                 :            : }
    3312                 :            : 
    3313                 :            : /* Try to verify that the sizes and lengths of the arguments to a string
    3314                 :            :    manipulation function given by EXP are within valid bounds and that
    3315                 :            :    the operation does not lead to buffer overflow or read past the end.
    3316                 :            :    Arguments other than EXP may be null.  When non-null, the arguments
    3317                 :            :    have the following meaning:
    3318                 :            :    DST is the destination of a copy call or NULL otherwise.
    3319                 :            :    SRC is the source of a copy call or NULL otherwise.
    3320                 :            :    DSTWRITE is the number of bytes written into the destination obtained
    3321                 :            :    from the user-supplied size argument to the function (such as in
    3322                 :            :    memcpy(DST, SRCs, DSTWRITE) or strncpy(DST, DRC, DSTWRITE).
    3323                 :            :    MAXREAD is the user-supplied bound on the length of the source sequence
    3324                 :            :    (such as in strncat(d, s, N).  It specifies the upper limit on the number
    3325                 :            :    of bytes to write.  If NULL, it's taken to be the same as DSTWRITE.
    3326                 :            :    SRCSTR is the source string (such as in strcpy(DST, SRC)) when the
    3327                 :            :    expression EXP is a string function call (as opposed to a memory call
    3328                 :            :    like memcpy).  As an exception, SRCSTR can also be an integer denoting
    3329                 :            :    the precomputed size of the source string or object (for functions like
    3330                 :            :    memcpy).
    3331                 :            :    DSTSIZE is the size of the destination object specified by the last
    3332                 :            :    argument to the _chk builtins, typically resulting from the expansion
    3333                 :            :    of __builtin_object_size (such as in __builtin___strcpy_chk(DST, SRC,
    3334                 :            :    DSTSIZE).
    3335                 :            : 
    3336                 :            :    When DSTWRITE is null LEN is checked to verify that it doesn't exceed
    3337                 :            :    SIZE_MAX.
    3338                 :            : 
    3339                 :            :    If the call is successfully verified as safe return true, otherwise
    3340                 :            :    return false.  */
    3341                 :            : 
    3342                 :            : bool
    3343                 :     235255 : check_access (tree exp, tree, tree, tree dstwrite,
    3344                 :            :               tree maxread, tree srcstr, tree dstsize)
    3345                 :            : {
    3346                 :     235255 :   int opt = OPT_Wstringop_overflow_;
    3347                 :            : 
    3348                 :            :   /* The size of the largest object is half the address space, or
    3349                 :            :      PTRDIFF_MAX.  (This is way too permissive.)  */
    3350                 :     235255 :   tree maxobjsize = max_object_size ();
    3351                 :            : 
    3352                 :            :   /* Either the length of the source string for string functions or
    3353                 :            :      the size of the source object for raw memory functions.  */
    3354                 :     235255 :   tree slen = NULL_TREE;
    3355                 :            : 
    3356                 :     235255 :   tree range[2] = { NULL_TREE, NULL_TREE };
    3357                 :            : 
    3358                 :            :   /* Set to true when the exact number of bytes written by a string
    3359                 :            :      function like strcpy is not known and the only thing that is
    3360                 :            :      known is that it must be at least one (for the terminating nul).  */
    3361                 :     235255 :   bool at_least_one = false;
    3362                 :     235255 :   if (srcstr)
    3363                 :            :     {
    3364                 :            :       /* SRCSTR is normally a pointer to string but as a special case
    3365                 :            :          it can be an integer denoting the length of a string.  */
    3366                 :     123938 :       if (POINTER_TYPE_P (TREE_TYPE (srcstr)))
    3367                 :            :         {
    3368                 :            :           /* Try to determine the range of lengths the source string
    3369                 :            :              refers to.  If it can be determined and is less than
    3370                 :            :              the upper bound given by MAXREAD add one to it for
    3371                 :            :              the terminating nul.  Otherwise, set it to one for
    3372                 :            :              the same reason, or to MAXREAD as appropriate.  */
    3373                 :       4712 :           c_strlen_data lendata = { };
    3374                 :       4712 :           get_range_strlen (srcstr, &lendata, /* eltsize = */ 1);
    3375                 :       4712 :           range[0] = lendata.minlen;
    3376                 :       4712 :           range[1] = lendata.maxbound ? lendata.maxbound : lendata.maxlen;
    3377                 :       4712 :           if (range[0] && (!maxread || TREE_CODE (maxread) == INTEGER_CST))
    3378                 :            :             {
    3379                 :       4712 :               if (maxread && tree_int_cst_le (maxread, range[0]))
    3380                 :          0 :                 range[0] = range[1] = maxread;
    3381                 :            :               else
    3382                 :       4712 :                 range[0] = fold_build2 (PLUS_EXPR, size_type_node,
    3383                 :            :                                         range[0], size_one_node);
    3384                 :            : 
    3385                 :       4712 :               if (maxread && tree_int_cst_le (maxread, range[1]))
    3386                 :          0 :                 range[1] = maxread;
    3387                 :       4712 :               else if (!integer_all_onesp (range[1]))
    3388                 :       2120 :                 range[1] = fold_build2 (PLUS_EXPR, size_type_node,
    3389                 :            :                                         range[1], size_one_node);
    3390                 :            : 
    3391                 :       4712 :               slen = range[0];
    3392                 :            :             }
    3393                 :            :           else
    3394                 :            :             {
    3395                 :          0 :               at_least_one = true;
    3396                 :          0 :               slen = size_one_node;
    3397                 :            :             }
    3398                 :            :         }
    3399                 :            :       else
    3400                 :            :         slen = srcstr;
    3401                 :            :     }
    3402                 :            : 
    3403                 :     235255 :   if (!dstwrite && !maxread)
    3404                 :            :     {
    3405                 :            :       /* When the only available piece of data is the object size
    3406                 :            :          there is nothing to do.  */
    3407                 :       2458 :       if (!slen)
    3408                 :            :         return true;
    3409                 :            : 
    3410                 :            :       /* Otherwise, when the length of the source sequence is known
    3411                 :            :          (as with strlen), set DSTWRITE to it.  */
    3412                 :       2441 :       if (!range[0])
    3413                 :         34 :         dstwrite = slen;
    3414                 :            :     }
    3415                 :            : 
    3416                 :     235238 :   if (!dstsize)
    3417                 :     203838 :     dstsize = maxobjsize;
    3418                 :            : 
    3419                 :     235238 :   if (dstwrite)
    3420                 :     231869 :     get_size_range (dstwrite, range);
    3421                 :            : 
    3422                 :     235238 :   tree func = get_callee_fndecl (exp);
    3423                 :            : 
    3424                 :            :   /* First check the number of bytes to be written against the maximum
    3425                 :            :      object size.  */
    3426                 :     235238 :   if (range[0]
    3427                 :     234276 :       && TREE_CODE (range[0]) == INTEGER_CST
    3428                 :     469513 :       && tree_int_cst_lt (maxobjsize, range[0]))
    3429                 :            :     {
    3430                 :        102 :       if (TREE_NO_WARNING (exp))
    3431                 :            :         return false;
    3432                 :            : 
    3433                 :         63 :       location_t loc = tree_nonartificial_location (exp);
    3434                 :         63 :       loc = expansion_point_location_if_in_system_header (loc);
    3435                 :            : 
    3436                 :         63 :       bool warned;
    3437                 :         63 :       if (range[0] == range[1])
    3438                 :         63 :         warned = (func
    3439                 :         63 :                   ? warning_at (loc, opt,
    3440                 :            :                                 "%K%qD specified size %E "
    3441                 :            :                                 "exceeds maximum object size %E",
    3442                 :            :                                 exp, func, range[0], maxobjsize)
    3443                 :          0 :                   : warning_at (loc, opt,
    3444                 :            :                                 "%Kspecified size %E "
    3445                 :            :                                 "exceeds maximum object size %E",
    3446                 :            :                                 exp, range[0], maxobjsize));
    3447                 :            :       else
    3448                 :          0 :         warned = (func
    3449                 :          0 :                   ? warning_at (loc, opt,
    3450                 :            :                                 "%K%qD specified size between %E and %E "
    3451                 :            :                                 "exceeds maximum object size %E",
    3452                 :            :                                 exp, func,
    3453                 :            :                                 range[0], range[1], maxobjsize)
    3454                 :          0 :                   : warning_at (loc, opt,
    3455                 :            :                                 "%Kspecified size between %E and %E "
    3456                 :            :                                 "exceeds maximum object size %E",
    3457                 :            :                                 exp, range[0], range[1], maxobjsize));
    3458                 :         63 :       if (warned)
    3459                 :          4 :         TREE_NO_WARNING (exp) = true;
    3460                 :            : 
    3461                 :         63 :       return false;
    3462                 :            :     }
    3463                 :            : 
    3464                 :            :   /* The number of bytes to write is "exact" if DSTWRITE is non-null,
    3465                 :            :      constant, and in range of unsigned HOST_WIDE_INT.  */
    3466                 :     235136 :   bool exactwrite = dstwrite && tree_fits_uhwi_p (dstwrite);
    3467                 :            : 
    3468                 :            :   /* Next check the number of bytes to be written against the destination
    3469                 :            :      object size.  */
    3470                 :     235136 :   if (range[0] || !exactwrite || integer_all_onesp (dstwrite))
    3471                 :            :     {
    3472                 :     235136 :       if (range[0]
    3473                 :     234174 :           && TREE_CODE (range[0]) == INTEGER_CST
    3474                 :     469309 :           && ((tree_fits_uhwi_p (dstsize)
    3475                 :     233867 :                && tree_int_cst_lt (dstsize, range[0]))
    3476                 :     233309 :               || (dstwrite
    3477                 :     230948 :                   && tree_fits_uhwi_p (dstwrite)
    3478                 :     156855 :                   && tree_int_cst_lt (dstwrite, range[0]))))
    3479                 :            :         {
    3480                 :        864 :           if (TREE_NO_WARNING (exp))
    3481                 :            :             return false;
    3482                 :            : 
    3483                 :        659 :           location_t loc = tree_nonartificial_location (exp);
    3484                 :        659 :           loc = expansion_point_location_if_in_system_header (loc);
    3485                 :            : 
    3486                 :        659 :           bool warned = false;
    3487                 :        659 :           if (dstwrite == slen && at_least_one)
    3488                 :            :             {
    3489                 :            :               /* This is a call to strcpy with a destination of 0 size
    3490                 :            :                  and a source of unknown length.  The call will write
    3491                 :            :                  at least one byte past the end of the destination.  */
    3492                 :          0 :               warned = (func
    3493                 :          0 :                         ? warning_at (loc, opt,
    3494                 :            :                                       "%K%qD writing %E or more bytes into "
    3495                 :            :                                       "a region of size %E overflows "
    3496                 :            :                                       "the destination",
    3497                 :            :                                       exp, func, range[0], dstsize)
    3498                 :          0 :                         : warning_at (loc, opt,
    3499                 :            :                                       "%Kwriting %E or more bytes into "
    3500                 :            :                                       "a region of size %E overflows "
    3501                 :            :                                       "the destination",
    3502                 :            :                                       exp, range[0], dstsize));
    3503                 :            :             }
    3504                 :        659 :           else if (tree_int_cst_equal (range[0], range[1]))
    3505                 :        591 :             warned = (func
    3506                 :        591 :                       ? warning_n (loc, opt, tree_to_uhwi (range[0]),
    3507                 :            :                                    "%K%qD writing %E byte into a region "
    3508                 :            :                                    "of size %E overflows the destination",
    3509                 :            :                                    "%K%qD writing %E bytes into a region "
    3510                 :            :                                    "of size %E overflows the destination",
    3511                 :            :                                    exp, func, range[0], dstsize)
    3512                 :         18 :                       : warning_n (loc, opt, tree_to_uhwi (range[0]),
    3513                 :            :                                    "%Kwriting %E byte into a region "
    3514                 :            :                                    "of size %E overflows the destination",
    3515                 :            :                                    "%Kwriting %E bytes into a region "
    3516                 :            :                                    "of size %E overflows the destination",
    3517                 :            :                                    exp, range[0], dstsize));
    3518                 :         68 :           else if (tree_int_cst_sign_bit (range[1]))
    3519                 :            :             {
    3520                 :            :               /* Avoid printing the upper bound if it's invalid.  */
    3521                 :         25 :               warned = (func
    3522                 :         25 :                         ? warning_at (loc, opt,
    3523                 :            :                                       "%K%qD writing %E or more bytes into "
    3524                 :            :                                       "a region of size %E overflows "
    3525                 :            :                                       "the destination",
    3526                 :            :                                       exp, func, range[0], dstsize)
    3527                 :          0 :                         : warning_at (loc, opt,
    3528                 :            :                                       "%Kwriting %E or more bytes into "
    3529                 :            :                                       "a region of size %E overflows "
    3530                 :            :                                       "the destination",
    3531                 :            :                                       exp, range[0], dstsize));
    3532                 :            :             }
    3533                 :            :           else
    3534                 :         43 :             warned = (func
    3535                 :         43 :                       ? warning_at (loc, opt,
    3536                 :            :                                     "%K%qD writing between %E and %E bytes "
    3537                 :            :                                     "into a region of size %E overflows "
    3538                 :            :                                     "the destination",
    3539                 :            :                                     exp, func, range[0], range[1],
    3540                 :            :                                     dstsize)
    3541                 :          0 :                       : warning_at (loc, opt,
    3542                 :            :                                     "%Kwriting between %E and %E bytes "
    3543                 :            :                                     "into a region of size %E overflows "
    3544                 :            :                                     "the destination",
    3545                 :            :                                     exp, range[0], range[1],
    3546                 :            :                                     dstsize));
    3547                 :        659 :           if (warned)
    3548                 :        436 :             TREE_NO_WARNING (exp) = true;
    3549                 :            : 
    3550                 :            :           /* Return error when an overflow has been detected.  */
    3551                 :        659 :           return false;
    3552                 :            :         }
    3553                 :            :     }
    3554                 :            : 
    3555                 :            :   /* Check the maximum length of the source sequence against the size
    3556                 :            :      of the destination object if known, or against the maximum size
    3557                 :            :      of an object.  */
    3558                 :     234272 :   if (maxread)
    3559                 :            :     {
    3560                 :        962 :       get_size_range (maxread, range);
    3561                 :        962 :       if (range[0] && dstsize && tree_fits_uhwi_p (dstsize))
    3562                 :            :         {
    3563                 :        904 :           location_t loc = tree_nonartificial_location (exp);
    3564                 :        904 :           loc = expansion_point_location_if_in_system_header (loc);
    3565                 :            : 
    3566                 :        904 :           if (tree_int_cst_lt (maxobjsize, range[0]))
    3567                 :            :             {
    3568                 :          9 :               if (TREE_NO_WARNING (exp))
    3569                 :            :                 return false;
    3570                 :            : 
    3571                 :          7 :               bool warned = false;
    3572                 :            : 
    3573                 :            :               /* Warn about crazy big sizes first since that's more
    3574                 :            :                  likely to be meaningful than saying that the bound
    3575                 :            :                  is greater than the object size if both are big.  */
    3576                 :          7 :               if (range[0] == range[1])
    3577                 :          7 :                 warned = (func
    3578                 :          7 :                           ? warning_at (loc, opt,
    3579                 :            :                                         "%K%qD specified bound %E "
    3580                 :            :                                         "exceeds maximum object size %E",
    3581                 :            :                                         exp, func, range[0], maxobjsize)
    3582                 :          0 :                           : warning_at (loc, opt,
    3583                 :            :                                         "%Kspecified bound %E "
    3584                 :            :                                         "exceeds maximum object size %E",
    3585                 :            :                                         exp, range[0], maxobjsize));
    3586                 :            :               else
    3587                 :          0 :                 warned = (func
    3588                 :          0 :                           ? warning_at (loc, opt,
    3589                 :            :                                         "%K%qD specified bound between "
    3590                 :            :                                         "%E and %E exceeds maximum object "
    3591                 :            :                                         "size %E",
    3592                 :            :                                         exp, func,
    3593                 :            :                                         range[0], range[1], maxobjsize)
    3594                 :          0 :                           : warning_at (loc, opt,
    3595                 :            :                                         "%Kspecified bound between "
    3596                 :            :                                         "%E and %E exceeds maximum object "
    3597                 :            :                                         "size %E",
    3598                 :            :                                         exp, range[0], range[1], maxobjsize));
    3599                 :          7 :               if (warned)
    3600                 :          1 :                 TREE_NO_WARNING (exp) = true;
    3601                 :            : 
    3602                 :          7 :               return false;
    3603                 :            :             }
    3604                 :            : 
    3605                 :        895 :           if (dstsize != maxobjsize && tree_int_cst_lt (dstsize, range[0]))
    3606                 :            :             {
    3607                 :         98 :               if (TREE_NO_WARNING (exp))
    3608                 :            :                 return false;
    3609                 :            : 
    3610                 :         98 :               bool warned = false;
    3611                 :            : 
    3612                 :         98 :               if (tree_int_cst_equal (range[0], range[1]))
    3613                 :         92 :                 warned = (func
    3614                 :         92 :                           ? warning_at (loc, opt,
    3615                 :            :                                         "%K%qD specified bound %E "
    3616                 :            :                                         "exceeds destination size %E",
    3617                 :            :                                         exp, func,
    3618                 :            :                                         range[0], dstsize)
    3619                 :          0 :                           : warning_at (loc, opt,
    3620                 :            :                                         "%Kspecified bound %E "
    3621                 :            :                                         "exceeds destination size %E",
    3622                 :            :                                         exp, range[0], dstsize));
    3623                 :            :               else
    3624                 :          6 :                 warned = (func
    3625                 :          6 :                           ? warning_at (loc, opt,
    3626                 :            :                                         "%K%qD specified bound between %E "
    3627                 :            :                                         "and %E exceeds destination size %E",
    3628                 :            :                                         exp, func,
    3629                 :            :                                         range[0], range[1], dstsize)
    3630                 :          0 :                           : warning_at (loc, opt,
    3631                 :            :                                         "%Kspecified bound between %E "
    3632                 :            :                                         "and %E exceeds destination size %E",
    3633                 :            :                                         exp,
    3634                 :            :                                         range[0], range[1], dstsize));
    3635                 :         98 :               if (warned)
    3636                 :         25 :                 TREE_NO_WARNING (exp) = true;
    3637                 :            : 
    3638                 :         98 :               return false;
    3639                 :            :             }
    3640                 :            :         }
    3641                 :            :     }
    3642                 :            : 
    3643                 :            :   /* Check for reading past the end of SRC.  */
    3644                 :     234165 :   if (slen
    3645                 :     234165 :       && slen == srcstr
    3646                 :     118856 :       && dstwrite && range[0]
    3647                 :     352413 :       && tree_int_cst_lt (slen, range[0]))
    3648                 :            :     {
    3649                 :        205 :       if (TREE_NO_WARNING (exp))
    3650                 :            :         return false;
    3651                 :            : 
    3652                 :        199 :       bool warned = false;
    3653                 :        199 :       location_t loc = tree_nonartificial_location (exp);
    3654                 :        199 :       loc = expansion_point_location_if_in_system_header (loc);
    3655                 :            : 
    3656                 :        199 :       if (tree_int_cst_equal (range[0], range[1]))
    3657                 :        189 :         warned = (func
    3658                 :        189 :                   ? warning_n (loc, opt, tree_to_uhwi (range[0]),
    3659                 :            :                                "%K%qD reading %E byte from a region of size %E",
    3660                 :            :                                "%K%qD reading %E bytes from a region of size %E",
    3661                 :            :                                exp, func, range[0], slen)
    3662                 :          2 :                   : warning_n (loc, opt, tree_to_uhwi (range[0]),
    3663                 :            :                                "%Kreading %E byte from a region of size %E",
    3664                 :            :                                "%Kreading %E bytes from a region of size %E",
    3665                 :            :                                exp, range[0], slen));
    3666                 :         10 :       else if (tree_int_cst_sign_bit (range[1]))
    3667                 :            :         {
    3668                 :            :           /* Avoid printing the upper bound if it's invalid.  */
    3669                 :          0 :           warned = (func
    3670                 :          0 :                     ? warning_at (loc, opt,
    3671                 :            :                                   "%K%qD reading %E or more bytes from a region "
    3672                 :            :                                   "of size %E",
    3673                 :            :                                   exp, func, range[0], slen)
    3674                 :          0 :                     : warning_at (loc, opt,
    3675                 :            :                                   "%Kreading %E or more bytes from a region "
    3676                 :            :                                   "of size %E",
    3677                 :            :                                   exp, range[0], slen));
    3678                 :            :         }
    3679                 :            :       else
    3680                 :         10 :         warned = (func
    3681                 :         10 :                   ? warning_at (loc, opt,
    3682                 :            :                                 "%K%qD reading between %E and %E bytes from "
    3683                 :            :                                 "a region of size %E",
    3684                 :            :                                 exp, func, range[0], range[1], slen)
    3685                 :          0 :                   : warning_at (loc, opt,
    3686                 :            :                                 "%Kreading between %E and %E bytes from "
    3687                 :            :                                 "a region of size %E",
    3688                 :            :                                 exp, range[0], range[1], slen));
    3689                 :        199 :       if (warned)
    3690                 :        113 :         TREE_NO_WARNING (exp) = true;
    3691                 :            : 
    3692                 :        199 :       return false;
    3693                 :            :     }
    3694                 :            : 
    3695                 :            :   return true;
    3696                 :            : }
    3697                 :            : 
    3698                 :            : /* If STMT is a call to an allocation function, returns the constant
    3699                 :            :    size of the object allocated by the call represented as sizetype.
    3700                 :            :    If nonnull, sets RNG1[] to the range of the size.  */
    3701                 :            : 
    3702                 :            : tree
    3703                 :     431733 : gimple_call_alloc_size (gimple *stmt, wide_int rng1[2] /* = NULL */,
    3704                 :            :                         const vr_values *rvals /* = NULL */)
    3705                 :            : {
    3706                 :     431733 :   if (!stmt)
    3707                 :            :     return NULL_TREE;
    3708                 :            : 
    3709                 :      88650 :   tree allocfntype;
    3710                 :      88650 :   if (tree fndecl = gimple_call_fndecl (stmt))
    3711                 :      88623 :     allocfntype = TREE_TYPE (fndecl);
    3712                 :            :   else
    3713                 :         27 :     allocfntype = gimple_call_fntype (stmt);
    3714                 :            : 
    3715                 :      88650 :   if (!allocfntype)
    3716                 :            :     return NULL_TREE;
    3717                 :            : 
    3718                 :      88650 :   unsigned argidx1 = UINT_MAX, argidx2 = UINT_MAX;
    3719                 :      88650 :   tree at = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (allocfntype));
    3720                 :      88650 :   if (!at)
    3721                 :            :     {
    3722                 :      77442 :       if (!gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
    3723                 :            :         return NULL_TREE;
    3724                 :            : 
    3725                 :            :       argidx1 = 0;
    3726                 :            :     }
    3727                 :            : 
    3728                 :      17882 :   unsigned nargs = gimple_call_num_args (stmt);
    3729                 :            : 
    3730                 :      17882 :   if (argidx1 == UINT_MAX)
    3731                 :            :     {
    3732                 :      11208 :       tree atval = TREE_VALUE (at);
    3733                 :      11208 :       if (!atval)
    3734                 :            :         return NULL_TREE;
    3735                 :            : 
    3736                 :      11208 :       argidx1 = TREE_INT_CST_LOW (TREE_VALUE (atval)) - 1;
    3737                 :      11208 :       if (nargs <= argidx1)
    3738                 :            :         return NULL_TREE;
    3739                 :            : 
    3740                 :      11208 :       atval = TREE_CHAIN (atval);
    3741                 :      11208 :       if (atval)
    3742                 :            :         {
    3743                 :        555 :           argidx2 = TREE_INT_CST_LOW (TREE_VALUE (atval)) - 1;
    3744                 :        555 :           if (nargs <= argidx2)
    3745                 :            :             return NULL_TREE;
    3746                 :            :         }
    3747                 :            :     }
    3748                 :            : 
    3749                 :      17882 :   tree size = gimple_call_arg (stmt, argidx1);
    3750                 :            : 
    3751                 :      17882 :   wide_int rng1_buf[2];
    3752                 :            :   /* If RNG1 is not set, use the buffer.  */
    3753                 :      17882 :   if (!rng1)
    3754                 :      15784 :     rng1 = rng1_buf;
    3755                 :            : 
    3756                 :      17882 :   if (!get_range (size, rng1, rvals))
    3757                 :            :     return NULL_TREE;
    3758                 :            : 
    3759                 :       9695 :   if (argidx2 > nargs && TREE_CODE (size) == INTEGER_CST)
    3760                 :       3324 :     return fold_convert (sizetype, size);
    3761                 :            : 
    3762                 :            :   /* To handle ranges do the math in wide_int and return the product
    3763                 :            :      of the upper bounds as a constant.  Ignore anti-ranges.  */
    3764                 :       6371 :   tree n = argidx2 < nargs ? gimple_call_arg (stmt, argidx2) : integer_one_node;
    3765                 :       6371 :   wide_int rng2[2];
    3766                 :       6371 :   if (!get_range (n, rng2, rvals))
    3767                 :            :     return NULL_TREE;
    3768                 :            : 
    3769                 :            :   /* Extend to the maximum precision to avoid overflow.  */
    3770                 :       6343 :   const int prec = ADDR_MAX_PRECISION;
    3771                 :       6343 :   rng1[0] = wide_int::from (rng1[0], prec, UNSIGNED);
    3772                 :       6343 :   rng1[1] = wide_int::from (rng1[1], prec, UNSIGNED);
    3773                 :       6343 :   rng2[0] = wide_int::from (rng2[0], prec, UNSIGNED);
    3774                 :       6343 :   rng2[1] = wide_int::from (rng2[1], prec, UNSIGNED);
    3775                 :            : 
    3776                 :            :   /* Compute products of both bounds for the caller but return the lesser
    3777                 :            :      of SIZE_MAX and the product of the upper bounds as a constant.  */
    3778                 :       6343 :   rng1[0] = rng1[0] * rng2[0];
    3779                 :       6343 :   rng1[1] = rng1[1] * rng2[1];
    3780                 :       6343 :   tree size_max = TYPE_MAX_VALUE (sizetype);
    3781                 :       6343 :   if (wi::gtu_p (rng1[1], wi::to_wide (size_max, prec)))
    3782                 :            :     {
    3783                 :         19 :       rng1[1] = wi::to_wide (size_max);
    3784                 :         19 :       return size_max;
    3785                 :            :     }
    3786                 :            : 
    3787                 :       6324 :   return wide_int_to_tree (sizetype, rng1[1]);
    3788                 :            : }
    3789                 :            : 
    3790                 :            : /* Helper for compute_objsize.  Returns the constant size of the DEST
    3791                 :            :    if it refers to a variable or field and sets *PDECL to the DECL and
    3792                 :            :    *POFF to zero.  Otherwise returns null for other nodes.  */
    3793                 :            : 
    3794                 :            : static tree
    3795                 :     779680 : addr_decl_size (tree dest, tree *pdecl, tree *poff)
    3796                 :            : {
    3797                 :     779680 :   if (TREE_CODE (dest) == ADDR_EXPR)
    3798                 :      66489 :     dest = TREE_OPERAND (dest, 0);
    3799                 :            : 
    3800                 :     779680 :   if (DECL_P (dest))
    3801                 :            :     {
    3802                 :      83614 :       *pdecl = dest;
    3803                 :      83614 :       *poff = integer_zero_node;
    3804                 :      83614 :       if (tree size = DECL_SIZE_UNIT (dest))
    3805                 :      82817 :         return TREE_CODE (size) == INTEGER_CST ? size : NULL_TREE;
    3806                 :            :     }
    3807                 :            : 
    3808                 :     696865 :   if (TREE_CODE (dest) == COMPONENT_REF)
    3809                 :            :     {
    3810                 :      55608 :       *pdecl = TREE_OPERAND (dest, 1);
    3811                 :      55608 :       *poff = integer_zero_node;
    3812                 :            :       /* Only return constant sizes for now while callers depend on it.  */
    3813                 :      55608 :       if (tree size = component_ref_size (dest))
    3814                 :      55276 :         return TREE_CODE (size) == INTEGER_CST ? size : NULL_TREE;
    3815                 :            :     }
    3816                 :            : 
    3817                 :            :   return NULL_TREE;
    3818                 :            : }
    3819                 :            : 
    3820                 :            : /* Helper to compute the size of the object referenced by the DEST
    3821                 :            :    expression which must have pointer type, using Object Size type
    3822                 :            :    OSTYPE (only the least significant 2 bits are used).
    3823                 :            :    Returns an estimate of the size of the object represented as
    3824                 :            :    a sizetype constant if successful or NULL when the size cannot
    3825                 :            :    be determined.
    3826                 :            :    When the referenced object involves a non-constant offset in some
    3827                 :            :    range the returned value represents the largest size given the
    3828                 :            :    smallest non-negative offset in the range.
    3829                 :            :    If nonnull, sets *PDECL to the decl of the referenced subobject
    3830                 :            :    if it can be determined, or to null otherwise.  Likewise, when
    3831                 :            :    POFF is nonnull *POFF is set to the offset into *PDECL.
    3832                 :            : 
    3833                 :            :    The function is intended for diagnostics and should not be used
    3834                 :            :    to influence code generation or optimization.  */
    3835                 :            : 
    3836                 :            : tree
    3837                 :    1223210 : compute_objsize (tree dest, int ostype, tree *pdecl /* = NULL */,
    3838                 :            :                  tree *poff /* = NULL */, const vr_values *rvals /* = NULL */)
    3839                 :            : {
    3840                 :    1223210 :   tree dummy_decl = NULL_TREE;
    3841                 :    1223210 :   if (!pdecl)
    3842                 :     478084 :     pdecl = &dummy_decl;
    3843                 :            : 
    3844                 :    1223210 :   tree dummy_off = NULL_TREE;
    3845                 :    1223210 :   if (!poff)
    3846                 :     478084 :     poff = &dummy_off;
    3847                 :            : 
    3848                 :            :   /* Only the two least significant bits are meaningful.  */
    3849                 :    1223210 :   ostype &= 3;
    3850                 :            : 
    3851                 :    1223210 :   if (ostype)
    3852                 :            :     /* Except for overly permissive calls to memcpy and other raw
    3853                 :            :        memory functions with zero OSTYPE, detect the size from simple
    3854                 :            :        DECLs first to more reliably than compute_builtin_object_size
    3855                 :            :        set *PDECL and *POFF.  */
    3856                 :     755829 :     if (tree size = addr_decl_size (dest, pdecl, poff))
    3857                 :            :       return size;
    3858                 :            : 
    3859                 :    1086320 :   unsigned HOST_WIDE_INT size;
    3860                 :    1086320 :   if (compute_builtin_object_size (dest, ostype, &size, pdecl, poff))
    3861                 :     227042 :     return build_int_cst (sizetype, size);
    3862                 :            : 
    3863                 :     859277 :   if (TREE_CODE (dest) == SSA_NAME)
    3864                 :            :     {
    3865                 :     655964 :       gimple *stmt = SSA_NAME_DEF_STMT (dest);
    3866                 :     655964 :       if (is_gimple_call (stmt))
    3867                 :            :         {
    3868                 :            :           /* If STMT is a call to an allocation function get the size
    3869                 :            :              from its argument(s).  If successful, also set *PDECL to
    3870                 :            :              DEST for the caller to include in diagnostics.  */
    3871                 :      82962 :           if (tree size = gimple_call_alloc_size (stmt))
    3872                 :            :             {
    3873                 :       8119 :               *pdecl = dest;
    3874                 :       8119 :               *poff = integer_zero_node;
    3875                 :       8119 :               return size;
    3876                 :            :             }
    3877                 :            :           return NULL_TREE;
    3878                 :            :         }
    3879                 :            : 
    3880                 :     573002 :       if (!is_gimple_assign (stmt))
    3881                 :            :         return NULL_TREE;
    3882                 :            : 
    3883                 :     494082 :       dest = gimple_assign_rhs1 (stmt);
    3884                 :            : 
    3885                 :     494082 :       tree_code code = gimple_assign_rhs_code (stmt);
    3886                 :     494082 :       if (code == POINTER_PLUS_EXPR)
    3887                 :            :         {
    3888                 :            :           /* compute_builtin_object_size fails for addresses with
    3889                 :            :              non-constant offsets.  Try to determine the range of
    3890                 :            :              such an offset here and use it to adjust the constant
    3891                 :            :              size.  */
    3892                 :      36592 :           tree off = gimple_assign_rhs2 (stmt);
    3893                 :      36592 :           if (TREE_CODE (off) == INTEGER_CST)
    3894                 :            :             {
    3895                 :       8008 :               if (tree size = compute_objsize (dest, ostype, pdecl, poff))
    3896                 :            :                 {
    3897                 :        148 :                   wide_int wioff = wi::to_wide (off);
    3898                 :        148 :                   wide_int wisiz = wi::to_wide (size);
    3899                 :            : 
    3900                 :            :                   /* Ignore negative offsets for now.  For others,
    3901                 :            :                      use the lower bound as the most optimistic
    3902                 :            :                      estimate of the (remaining) size.  */
    3903                 :        148 :                   if (wi::neg_p (wioff))
    3904                 :            :                     ;
    3905                 :            :                   else
    3906                 :            :                     {
    3907                 :        148 :                       if (*poff)
    3908                 :            :                         {
    3909                 :        125 :                           *poff = fold_convert (ptrdiff_type_node, *poff);
    3910                 :        125 :                           off = fold_convert (ptrdiff_type_node, *poff);
    3911                 :        125 :                           *poff = size_binop (PLUS_EXPR, *poff, off);
    3912                 :            :                         }
    3913                 :            :                       else
    3914                 :         23 :                         *poff = off;
    3915                 :        148 :                       if (wi::ltu_p (wioff, wisiz))
    3916                 :        140 :                         return wide_int_to_tree (TREE_TYPE (size),
    3917                 :        280 :                                                  wi::sub (wisiz, wioff));
    3918                 :          8 :                       return size_zero_node;
    3919                 :            :                     }
    3920                 :            :                 }
    3921                 :            :             }
    3922                 :      28584 :           else if (TREE_CODE (off) == SSA_NAME
    3923                 :      57168 :                    && INTEGRAL_TYPE_P (TREE_TYPE (off)))
    3924                 :            :             {
    3925                 :      28584 :               wide_int min, max;
    3926                 :      28584 :               enum value_range_kind rng = get_range_info (off, &min, &max);
    3927                 :            : 
    3928                 :      28584 :               if (rng == VR_RANGE)
    3929                 :       9398 :                 if (tree size = compute_objsize (dest, ostype, pdecl, poff))
    3930                 :            :                   {
    3931                 :       3140 :                     wide_int wisiz = wi::to_wide (size);
    3932                 :            : 
    3933                 :            :                     /* Ignore negative offsets for now.  For others,
    3934                 :            :                        use the lower bound as the most optimistic
    3935                 :            :                        estimate of the (remaining)size.  */
    3936                 :       6234 :                     if (wi::neg_p (min) || wi::neg_p (max))
    3937                 :            :                       ;
    3938                 :            :                     else
    3939                 :            :                       {
    3940                 :            :                         /* FIXME: For now, since the offset is non-constant,
    3941                 :            :                            clear *POFF to keep it from being "misused."
    3942                 :            :                            Eventually *POFF will need to become a range that
    3943                 :            :                            can be properly added to the outer offset if it
    3944                 :            :                            too is one.  */
    3945                 :       2379 :                         *poff = NULL_TREE;
    3946                 :       2379 :                         if (wi::ltu_p (min, wisiz))
    3947                 :       2313 :                           return wide_int_to_tree (TREE_TYPE (size),
    3948                 :       4626 :                                                    wi::sub (wisiz, min));
    3949                 :         66 :                         return size_zero_node;
    3950                 :            :                       }
    3951                 :            :                   }
    3952                 :            :             }
    3953                 :            :         }
    3954                 :     457490 :       else if (code != ADDR_EXPR)
    3955                 :            :         return NULL_TREE;
    3956                 :            :     }
    3957                 :            : 
    3958                 :            :   /* Unless computing the largest size (for memcpy and other raw memory
    3959                 :            :      functions), try to determine the size of the object from its type.  */
    3960                 :     243175 :   if (!ostype)
    3961                 :            :     return NULL_TREE;
    3962                 :            : 
    3963                 :     207703 :   if (TREE_CODE (dest) == ARRAY_REF
    3964                 :     147616 :       || TREE_CODE (dest) == MEM_REF)
    3965                 :            :     {
    3966                 :     183852 :       tree ref = TREE_OPERAND (dest, 0);
    3967                 :     183852 :       tree reftype = TREE_TYPE (ref);
    3968                 :     183852 :       if (TREE_CODE (dest) == MEM_REF && TREE_CODE (reftype) == POINTER_TYPE)
    3969                 :            :         {
    3970                 :            :           /* Give up for MEM_REFs of vector types; those may be synthesized
    3971                 :            :              from multiple assignments to consecutive data members.  See PR
    3972                 :            :              93200.
    3973                 :            :              FIXME: Deal with this more generally, e.g., by marking up such
    3974                 :            :              MEM_REFs at the time they're created.  */
    3975                 :     121522 :           reftype = TREE_TYPE (reftype);
    3976                 :     121522 :           if (TREE_CODE (reftype) == VECTOR_TYPE)
    3977                 :            :             return NULL_TREE;
    3978                 :            :         }
    3979                 :     182900 :       tree off = TREE_OPERAND (dest, 1);
    3980                 :     182900 :       if (tree size = compute_objsize (ref, ostype, pdecl, poff))
    3981                 :            :         {
    3982                 :            :           /* If the declaration of the destination object is known
    3983                 :            :              to have zero size, return zero.  */
    3984                 :      74824 :           if (integer_zerop (size)
    3985                 :        203 :               && *pdecl && DECL_P (*pdecl)
    3986                 :      75026 :               && *poff && integer_zerop (*poff))
    3987                 :        201 :             return size_zero_node;
    3988                 :            : 
    3989                 :            :           /* A valid offset into a declared object cannot be negative.
    3990                 :            :              A zero size with a zero "inner" offset is still zero size
    3991                 :            :              regardless of the "other" offset OFF.  */
    3992                 :      74623 :           if (*poff
    3993                 :      74623 :               && ((integer_zerop (*poff) && integer_zerop (size))
    3994                 :      73904 :                   || (TREE_CODE (*poff) == INTEGER_CST
    3995                 :      73884 :                       && tree_int_cst_sgn (*poff) < 0)))
    3996                 :          0 :             return size_zero_node;
    3997                 :            : 
    3998                 :      74623 :           wide_int offrng[2];
    3999                 :      74623 :           if (!get_range (off, offrng, rvals))
    4000                 :            :             return NULL_TREE;
    4001                 :            : 
    4002                 :            :           /* Convert to the same precision to keep wide_int from "helpfully"
    4003                 :            :              crashing whenever it sees other arguments.  */
    4004                 :      74232 :           const unsigned sizprec = TYPE_PRECISION (sizetype);
    4005                 :      74232 :           offrng[0] = wide_int::from (offrng[0], sizprec, SIGNED);
    4006                 :      74232 :           offrng[1] = wide_int::from (offrng[1], sizprec, SIGNED);
    4007                 :            : 
    4008                 :            :           /* Adjust SIZE either up or down by the sum of *POFF and OFF
    4009                 :            :              above.  */
    4010                 :      74232 :           if (TREE_CODE (dest) == ARRAY_REF)
    4011                 :            :             {
    4012                 :      20357 :               tree lowbnd = array_ref_low_bound (dest);
    4013                 :      20357 :               if (!integer_zerop (lowbnd) && tree_fits_uhwi_p (lowbnd))
    4014                 :            :                 {
    4015                 :            :                   /* Adjust the offset by the low bound of the array
    4016                 :            :                      domain (normally zero but 1 in Fortran).  */
    4017                 :        381 :                   unsigned HOST_WIDE_INT lb = tree_to_uhwi (lowbnd);
    4018                 :        381 :                   offrng[0] -= lb;
    4019                 :        381 :                   offrng[1] -= lb;
    4020                 :            :                 }
    4021                 :            : 
    4022                 :            :               /* Convert the array index into a byte offset.  */
    4023                 :      20357 :               tree eltype = TREE_TYPE (dest);
    4024                 :      20357 :               tree tpsize = TYPE_SIZE_UNIT (eltype);
    4025                 :      20357 :               if (tpsize && TREE_CODE (tpsize) == INTEGER_CST)
    4026                 :            :                 {
    4027                 :      20229 :                   wide_int wsz = wi::to_wide (tpsize, offrng->get_precision ());
    4028                 :      20229 :                   offrng[0] *= wsz;
    4029                 :      20229 :                   offrng[1] *= wsz;
    4030                 :            :                 }
    4031                 :            :               else
    4032                 :            :                 return NULL_TREE;
    4033                 :            :             }
    4034                 :            : 
    4035                 :      74104 :           wide_int wisize = wi::to_wide (size);
    4036                 :            : 
    4037                 :      74104 :           if (!*poff)
    4038                 :            :             {
    4039                 :            :               /* If the "inner" offset is unknown and the "outer" offset
    4040                 :            :                  is either negative or less than SIZE, return the size
    4041                 :            :                  minus the offset.  This may be overly optimistic in
    4042                 :            :                  the first case if the inner offset happens to be less
    4043                 :            :                  than the absolute value of the outer offset.  */
    4044                 :        719 :               if (wi::neg_p (offrng[0]))
    4045                 :            :                 return size;
    4046                 :        717 :               if (wi::ltu_p (offrng[0], wisize))
    4047                 :       1418 :                 return build_int_cst (sizetype, (wisize - offrng[0]).to_uhwi ());
    4048                 :          8 :               return size_zero_node;
    4049                 :            :             }
    4050                 :            : 
    4051                 :            :           /* Convert to the same precision to keep wide_int from "helpfuly"
    4052                 :            :              crashing whenever it sees other argumments.  */
    4053                 :      73385 :           offrng[0] = wide_int::from (offrng[0], sizprec, SIGNED);
    4054                 :      73385 :           offrng[1] = wide_int::from (offrng[1], sizprec, SIGNED);
    4055                 :            : 
    4056                 :      73385 :           tree dstoff = *poff;
    4057                 :      73385 :           if (integer_zerop (*poff))
    4058                 :      73156 :             *poff = off;
    4059                 :        229 :           else if (!integer_zerop (off))
    4060                 :            :             {
    4061                 :        217 :               *poff = fold_convert (ptrdiff_type_node, *poff);
    4062                 :        217 :               off = fold_convert (ptrdiff_type_node, off);
    4063                 :        217 :               *poff = size_binop (PLUS_EXPR, *poff, off);
    4064                 :            :             }
    4065                 :            : 
    4066                 :      73385 :           if (!wi::neg_p (offrng[0]))
    4067                 :            :             {
    4068                 :      73248 :               if (TREE_CODE (size) != INTEGER_CST)
    4069                 :            :                 return NULL_TREE;
    4070                 :            : 
    4071                 :            :               /* Return the difference between the size and the offset
    4072                 :            :                  or zero if the offset is greater.  */
    4073                 :      73248 :               wide_int wisize = wi::to_wide (size, sizprec);
    4074                 :      73248 :               if (wi::ltu_p (wisize, offrng[0]))
    4075                 :        260 :                 return size_zero_node;
    4076                 :            : 
    4077                 :      72988 :               return wide_int_to_tree (sizetype, wisize - offrng[0]);
    4078                 :            :             }
    4079                 :            : 
    4080                 :        137 :           wide_int dstoffrng[2];
    4081                 :        137 :           if (TREE_CODE (dstoff) == INTEGER_CST)
    4082                 :        133 :             dstoffrng[0] = dstoffrng[1] = wi::to_wide (dstoff);
    4083                 :          4 :           else if (TREE_CODE (dstoff) == SSA_NAME)
    4084                 :            :             {
    4085                 :          4 :               enum value_range_kind rng
    4086                 :          4 :                 = get_range_info (dstoff, dstoffrng, dstoffrng + 1);
    4087                 :          4 :               if (rng != VR_RANGE)
    4088                 :            :                 return NULL_TREE;
    4089                 :            :             }
    4090                 :            :           else
    4091                 :            :             return NULL_TREE;
    4092                 :            : 
    4093                 :        137 :           dstoffrng[0] = wide_int::from (dstoffrng[0], sizprec, SIGNED);
    4094                 :        137 :           dstoffrng[1] = wide_int::from (dstoffrng[1], sizprec, SIGNED);
    4095                 :            : 
    4096                 :        137 :           if (!wi::neg_p (dstoffrng[0]))
    4097                 :        137 :             wisize += dstoffrng[0];
    4098                 :            : 
    4099                 :        137 :           offrng[1] += dstoffrng[1];
    4100                 :        137 :           if (wi::neg_p (offrng[1]))
    4101                 :          0 :             return size_zero_node;
    4102                 :            : 
    4103                 :        137 :           return wide_int_to_tree (sizetype, wisize);
    4104                 :            :         }
    4105                 :            : 
    4106                 :            :       return NULL_TREE;
    4107                 :            :     }
    4108                 :            : 
    4109                 :            :   /* Try simple DECLs not handled above.  */
    4110                 :      23851 :   if (tree size = addr_decl_size (dest, pdecl, poff))
    4111                 :            :     return size;
    4112                 :            : 
    4113                 :      22758 :   tree type = TREE_TYPE (dest);
    4114                 :      22758 :   if (TREE_CODE (type) == POINTER_TYPE)
    4115                 :      18061 :     type = TREE_TYPE (type);
    4116                 :            : 
    4117                 :      22758 :   type = TYPE_MAIN_VARIANT (type);
    4118                 :      22758 :   if (TREE_CODE (dest) == ADDR_EXPR)
    4119                 :        628 :     dest = TREE_OPERAND (dest, 0);
    4120                 :            : 
    4121                 :      22758 :   if (TREE_CODE (type) == ARRAY_TYPE
    4122                 :      22758 :       && !array_at_struct_end_p (dest))
    4123                 :            :     {
    4124                 :        720 :       if (tree size = TYPE_SIZE_UNIT (type))
    4125                 :        356 :         return TREE_CODE (size) == INTEGER_CST ? size : NULL_TREE;
    4126                 :            :     }
    4127                 :            : 
    4128                 :            :   return NULL_TREE;
    4129                 :            : }
    4130                 :            : 
    4131                 :            : /* Helper to determine and check the sizes of the source and the destination
    4132                 :            :    of calls to __builtin_{bzero,memcpy,mempcpy,memset} calls.  EXP is the
    4133                 :            :    call expression, DEST is the destination argument, SRC is the source
    4134                 :            :    argument or null, and LEN is the number of bytes.  Use Object Size type-0
    4135                 :            :    regardless of the OPT_Wstringop_overflow_ setting.  Return true on success
    4136                 :            :    (no overflow or invalid sizes), false otherwise.  */
    4137                 :            : 
    4138                 :            : static bool
    4139                 :      76946 : check_memop_access (tree exp, tree dest, tree src, tree size)
    4140                 :            : {
    4141                 :            :   /* For functions like memset and memcpy that operate on raw memory
    4142                 :            :      try to determine the size of the largest source and destination
    4143                 :            :      object using type-0 Object Size regardless of the object size
    4144                 :            :      type specified by the option.  */
    4145                 :      76946 :   tree srcsize = src ? compute_objsize (src, 0) : NULL_TREE;
    4146                 :      76946 :   tree dstsize = compute_objsize (dest, 0);
    4147                 :            : 
    4148                 :      76946 :   return check_access (exp, dest, src, size, /*maxread=*/NULL_TREE,
    4149                 :      76946 :                        srcsize, dstsize);
    4150                 :            : }
    4151                 :            : 
    4152                 :            : /* Validate memchr arguments without performing any expansion.
    4153                 :            :    Return NULL_RTX.  */
    4154                 :            : 
    4155                 :            : static rtx
    4156                 :        564 : expand_builtin_memchr (tree exp, rtx)
    4157                 :            : {
    4158                 :        564 :   if (!validate_arglist (exp,
    4159                 :            :                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4160                 :            :     return NULL_RTX;
    4161                 :            : 
    4162                 :        559 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4163                 :        559 :   tree len = CALL_EXPR_ARG (exp, 2);
    4164                 :            : 
    4165                 :            :   /* Diagnose calls where the specified length exceeds the size
    4166                 :            :      of the object.  */
    4167                 :        559 :   if (warn_stringop_overflow)
    4168                 :            :     {
    4169                 :        559 :       tree size = compute_objsize (arg1, 0);
    4170                 :        559 :       check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE, len,
    4171                 :            :                     /*maxread=*/NULL_TREE, size, /*objsize=*/NULL_TREE);
    4172                 :            :     }
    4173                 :            : 
    4174                 :            :   return NULL_RTX;
    4175                 :            : }
    4176                 :            : 
    4177                 :            : /* Expand a call EXP to the memcpy builtin.
    4178                 :            :    Return NULL_RTX if we failed, the caller should emit a normal call,
    4179                 :            :    otherwise try to get the result in TARGET, if convenient (and in
    4180                 :            :    mode MODE if that's convenient).  */
    4181                 :            : 
    4182                 :            : static rtx
    4183                 :      40645 : expand_builtin_memcpy (tree exp, rtx target)
    4184                 :            : {
    4185                 :      40645 :   if (!validate_arglist (exp,
    4186                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4187                 :            :     return NULL_RTX;
    4188                 :            : 
    4189                 :      40615 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4190                 :      40615 :   tree src = CALL_EXPR_ARG (exp, 1);
    4191                 :      40615 :   tree len = CALL_EXPR_ARG (exp, 2);
    4192                 :            : 
    4193                 :      40615 :   check_memop_access (exp, dest, src, len);
    4194                 :            : 
    4195                 :      40615 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    4196                 :      40615 :                                           /*retmode=*/ RETURN_BEGIN, false);
    4197                 :            : }
    4198                 :            : 
    4199                 :            : /* Check a call EXP to the memmove built-in for validity.
    4200                 :            :    Return NULL_RTX on both success and failure.  */
    4201                 :            : 
    4202                 :            : static rtx
    4203                 :      11187 : expand_builtin_memmove (tree exp, rtx target)
    4204                 :            : {
    4205                 :      11187 :   if (!validate_arglist (exp,
    4206                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4207                 :            :     return NULL_RTX;
    4208                 :            : 
    4209                 :      11152 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4210                 :      11152 :   tree src = CALL_EXPR_ARG (exp, 1);
    4211                 :      11152 :   tree len = CALL_EXPR_ARG (exp, 2);
    4212                 :            : 
    4213                 :      11152 :   check_memop_access (exp, dest, src, len);
    4214                 :            : 
    4215                 :      11152 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    4216                 :      11152 :                                           /*retmode=*/ RETURN_BEGIN, true);
    4217                 :            : }
    4218                 :            : 
    4219                 :            : /* Expand a call EXP to the mempcpy builtin.
    4220                 :            :    Return NULL_RTX if we failed; the caller should emit a normal call,
    4221                 :            :    otherwise try to get the result in TARGET, if convenient (and in
    4222                 :            :    mode MODE if that's convenient).  */
    4223                 :            : 
    4224                 :            : static rtx
    4225                 :       1635 : expand_builtin_mempcpy (tree exp, rtx target)
    4226                 :            : {
    4227                 :       1635 :   if (!validate_arglist (exp,
    4228                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4229                 :            :     return NULL_RTX;
    4230                 :            : 
    4231                 :       1628 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4232                 :       1628 :   tree src = CALL_EXPR_ARG (exp, 1);
    4233                 :       1628 :   tree len = CALL_EXPR_ARG (exp, 2);
    4234                 :            : 
    4235                 :            :   /* Policy does not generally allow using compute_objsize (which
    4236                 :            :      is used internally by check_memop_size) to change code generation
    4237                 :            :      or drive optimization decisions.
    4238                 :            : 
    4239                 :            :      In this instance it is safe because the code we generate has
    4240                 :            :      the same semantics regardless of the return value of
    4241                 :            :      check_memop_sizes.   Exactly the same amount of data is copied
    4242                 :            :      and the return value is exactly the same in both cases.
    4243                 :            : 
    4244                 :            :      Furthermore, check_memop_size always uses mode 0 for the call to
    4245                 :            :      compute_objsize, so the imprecise nature of compute_objsize is
    4246                 :            :      avoided.  */
    4247                 :            : 
    4248                 :            :   /* Avoid expanding mempcpy into memcpy when the call is determined
    4249                 :            :      to overflow the buffer.  This also prevents the same overflow
    4250                 :            :      from being diagnosed again when expanding memcpy.  */
    4251                 :       1628 :   if (!check_memop_access (exp, dest, src, len))
    4252                 :            :     return NULL_RTX;
    4253                 :            : 
    4254                 :       1614 :   return expand_builtin_mempcpy_args (dest, src, len,
    4255                 :       1614 :                                       target, exp, /*retmode=*/ RETURN_END);
    4256                 :            : }
    4257                 :            : 
    4258                 :            : /* Helper function to do the actual work for expand of memory copy family
    4259                 :            :    functions (memcpy, mempcpy, stpcpy).  Expansing should assign LEN bytes
    4260                 :            :    of memory from SRC to DEST and assign to TARGET if convenient.  Return
    4261                 :            :    value is based on RETMODE argument.  */
    4262                 :            : 
    4263                 :            : static rtx
    4264                 :      53404 : expand_builtin_memory_copy_args (tree dest, tree src, tree len,
    4265                 :            :                                  rtx target, tree exp, memop_ret retmode,
    4266                 :            :                                  bool might_overlap)
    4267                 :            : {
    4268                 :      53404 :   const char *src_str;
    4269                 :      53404 :   unsigned int src_align = get_pointer_alignment (src);
    4270                 :      53404 :   unsigned int dest_align = get_pointer_alignment (dest);
    4271                 :      53404 :   rtx dest_mem, src_mem, dest_addr, len_rtx;
    4272                 :      53404 :   HOST_WIDE_INT expected_size = -1;
    4273                 :      53404 :   unsigned int expected_align = 0;
    4274                 :      53404 :   unsigned HOST_WIDE_INT min_size;
    4275                 :      53404 :   unsigned HOST_WIDE_INT max_size;
    4276                 :      53404 :   unsigned HOST_WIDE_INT probable_max_size;
    4277                 :            : 
    4278                 :      53404 :   bool is_move_done;
    4279                 :            : 
    4280                 :            :   /* If DEST is not a pointer type, call the normal function.  */
    4281                 :      53404 :   if (dest_align == 0)
    4282                 :            :     return NULL_RTX;
    4283                 :            : 
    4284                 :            :   /* If either SRC is not a pointer type, don't do this
    4285                 :            :      operation in-line.  */
    4286                 :      53404 :   if (src_align == 0)
    4287                 :            :     return NULL_RTX;
    4288                 :            : 
    4289                 :      53404 :   if (currently_expanding_gimple_stmt)
    4290                 :      53404 :     stringop_block_profile (currently_expanding_gimple_stmt,
    4291                 :            :                             &expected_align, &expected_size);
    4292                 :            : 
    4293                 :      53404 :   if (expected_align < dest_align)
    4294                 :      53392 :     expected_align = dest_align;
    4295                 :      53404 :   dest_mem = get_memory_rtx (dest, len);
    4296                 :      53404 :   set_mem_align (dest_mem, dest_align);
    4297                 :      53404 :   len_rtx = expand_normal (len);
    4298                 :      53404 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    4299                 :            :                         &probable_max_size);
    4300                 :      53404 :   src_str = c_getstr (src);
    4301                 :            : 
    4302                 :            :   /* If SRC is a string constant and block move would be done by
    4303                 :            :      pieces, we can avoid loading the string from memory and only
    4304                 :            :      stored the computed constants.  This works in the overlap
    4305                 :            :      (memmove) case as well because store_by_pieces just generates a
    4306                 :            :      series of stores of constants from the string constant returned
    4307                 :            :      by c_getstr().  */
    4308                 :      53404 :   if (src_str
    4309                 :       7953 :       && CONST_INT_P (len_rtx)
    4310                 :       7892 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
    4311                 :      61216 :       && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
    4312                 :            :                               CONST_CAST (char *, src_str),
    4313                 :            :                               dest_align, false))
    4314                 :            :     {
    4315                 :       7720 :       dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
    4316                 :            :                                   builtin_memcpy_read_str,
    4317                 :            :                                   CONST_CAST (char *, src_str),
    4318                 :            :                                   dest_align, false, retmode);
    4319                 :       7720 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    4320                 :       7720 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4321                 :       7720 :       return dest_mem;
    4322                 :            :     }
    4323                 :            : 
    4324                 :      45684 :   src_mem = get_memory_rtx (src, len);
    4325                 :      45684 :   set_mem_align (src_mem, src_align);
    4326                 :            : 
    4327                 :            :   /* Copy word part most expediently.  */
    4328                 :      45684 :   enum block_op_methods method = BLOCK_OP_NORMAL;
    4329                 :      45684 :   if (CALL_EXPR_TAILCALL (exp)
    4330                 :      45684 :       && (retmode == RETURN_BEGIN || target == const0_rtx))
    4331                 :            :     method = BLOCK_OP_TAILCALL;
    4332                 :      45684 :   bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
    4333                 :      45684 :                            && retmode == RETURN_END
    4334                 :      45684 :                            && !might_overlap
    4335                 :      46974 :                            && target != const0_rtx);
    4336                 :       1020 :   if (use_mempcpy_call)
    4337                 :            :     method = BLOCK_OP_NO_LIBCALL_RET;
    4338                 :      45684 :   dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
    4339                 :            :                                      expected_align, expected_size,
    4340                 :            :                                      min_size, max_size, probable_max_size,
    4341                 :            :                                      use_mempcpy_call, &is_move_done, might_overlap);
    4342                 :            : 
    4343                 :            :   /* Bail out when a mempcpy call would be expanded as libcall and when
    4344                 :            :      we have a target that provides a fast implementation
    4345                 :            :      of mempcpy routine.  */
    4346                 :      45684 :   if (!is_move_done)
    4347                 :            :     return NULL_RTX;
    4348                 :            : 
    4349                 :      34303 :   if (dest_addr == pc_rtx)
    4350                 :            :     return NULL_RTX;
    4351                 :            : 
    4352                 :      34303 :   if (dest_addr == 0)
    4353                 :            :     {
    4354                 :      17839 :       dest_addr = force_operand (XEXP (dest_mem, 0), target);
    4355                 :      17839 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    4356                 :            :     }
    4357                 :            : 
    4358                 :      34303 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    4359                 :            :     {
    4360                 :        777 :       dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
    4361                 :            :       /* stpcpy pointer to last byte.  */
    4362                 :        777 :       if (retmode == RETURN_END_MINUS_ONE)
    4363                 :          0 :         dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
    4364                 :            :     }
    4365                 :            : 
    4366                 :            :   return dest_addr;
    4367                 :            : }
    4368                 :            : 
    4369                 :            : static rtx
    4370                 :       1637 : expand_builtin_mempcpy_args (tree dest, tree src, tree len,
    4371                 :            :                              rtx target, tree orig_exp, memop_ret retmode)
    4372                 :            : {
    4373                 :       1614 :   return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
    4374                 :          0 :                                           retmode, false);
    4375                 :            : }
    4376                 :            : 
    4377                 :            : /* Expand into a movstr instruction, if one is available.  Return NULL_RTX if
    4378                 :            :    we failed, the caller should emit a normal call, otherwise try to
    4379                 :            :    get the result in TARGET, if convenient.
    4380                 :            :    Return value is based on RETMODE argument.  */
    4381                 :            : 
    4382                 :            : static rtx
    4383                 :       1536 : expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
    4384                 :            : {
    4385                 :       1536 :   class expand_operand ops[3];
    4386                 :       1536 :   rtx dest_mem;
    4387                 :       1536 :   rtx src_mem;
    4388                 :            : 
    4389                 :       1536 :   if (!targetm.have_movstr ())
    4390                 :            :     return NULL_RTX;
    4391                 :            : 
    4392                 :          0 :   dest_mem = get_memory_rtx (dest, NULL);
    4393                 :          0 :   src_mem = get_memory_rtx (src, NULL);
    4394                 :          0 :   if (retmode == RETURN_BEGIN)
    4395                 :            :     {
    4396                 :          0 :       target = force_reg (Pmode, XEXP (dest_mem, 0));
    4397                 :          0 :       dest_mem = replace_equiv_address (dest_mem, target);
    4398                 :            :     }
    4399                 :            : 
    4400                 :          0 :   create_output_operand (&ops[0],
    4401                 :          0 :                          retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
    4402                 :          0 :   create_fixed_operand (&ops[1], dest_mem);
    4403                 :          0 :   create_fixed_operand (&ops[2], src_mem);
    4404                 :          0 :   if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
    4405                 :            :     return NULL_RTX;
    4406                 :            : 
    4407                 :          0 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    4408                 :            :     {
    4409                 :          0 :       target = ops[0].value;
    4410                 :            :       /* movstr is supposed to set end to the address of the NUL
    4411                 :            :          terminator.  If the caller requested a mempcpy-like return value,
    4412                 :            :          adjust it.  */
    4413                 :          0 :       if (retmode == RETURN_END)
    4414                 :            :         {
    4415                 :          0 :           rtx tem = plus_constant (GET_MODE (target),
    4416                 :          0 :                                    gen_lowpart (GET_MODE (target), target), 1);
    4417                 :          0 :           emit_move_insn (target, force_operand (tem, NULL_RTX));
    4418                 :            :         }
    4419                 :            :     }
    4420                 :            :   return target;
    4421                 :            : }
    4422                 :            : 
    4423                 :            : /* Do some very basic size validation of a call to the strcpy builtin
    4424                 :            :    given by EXP.  Return NULL_RTX to have the built-in expand to a call
    4425                 :            :    to the library function.  */
    4426                 :            : 
    4427                 :            : static rtx
    4428                 :        574 : expand_builtin_strcat (tree exp)
    4429                 :            : {
    4430                 :        574 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
    4431                 :        574 :       || !warn_stringop_overflow)
    4432                 :            :     return NULL_RTX;
    4433                 :            : 
    4434                 :        547 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4435                 :        547 :   tree src = CALL_EXPR_ARG (exp, 1);
    4436                 :            : 
    4437                 :            :   /* Detect unterminated source (only).  */
    4438                 :        547 :   if (!check_nul_terminated_array (exp, src))
    4439                 :            :     return NULL_RTX;
    4440                 :            : 
    4441                 :            :   /* There is no way here to determine the length of the string in
    4442                 :            :      the destination to which the SRC string is being appended so
    4443                 :            :      just diagnose cases when the souce string is longer than
    4444                 :            :      the destination object.  */
    4445                 :            : 
    4446                 :        546 :   tree destsize = compute_objsize (dest, warn_stringop_overflow - 1);
    4447                 :            : 
    4448                 :        546 :   check_access (exp, dest, src, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, src,
    4449                 :            :                 destsize);
    4450                 :            : 
    4451                 :        546 :   return NULL_RTX;
    4452                 :            : }
    4453                 :            : 
    4454                 :            : /* Expand expression EXP, which is a call to the strcpy builtin.  Return
    4455                 :            :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    4456                 :            :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    4457                 :            :    convenient).  */
    4458                 :            : 
    4459                 :            : static rtx
    4460                 :       1143 : expand_builtin_strcpy (tree exp, rtx target)
    4461                 :            : {
    4462                 :       1143 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    4463                 :            :     return NULL_RTX;
    4464                 :            : 
    4465                 :       1128 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4466                 :       1128 :   tree src = CALL_EXPR_ARG (exp, 1);
    4467                 :            : 
    4468                 :       1128 :   if (warn_stringop_overflow)
    4469                 :            :     {
    4470                 :        908 :       tree destsize = compute_objsize (dest, warn_stringop_overflow - 1);
    4471                 :        908 :       check_access (exp, dest, src, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE,
    4472                 :            :                     src, destsize);
    4473                 :            :     }
    4474                 :            : 
    4475                 :       1128 :   if (rtx ret = expand_builtin_strcpy_args (exp, dest, src, target))
    4476                 :            :     {
    4477                 :            :       /* Check to see if the argument was declared attribute nonstring
    4478                 :            :          and if so, issue a warning since at this point it's not known
    4479                 :            :          to be nul-terminated.  */
    4480                 :          0 :       tree fndecl = get_callee_fndecl (exp);
    4481                 :          0 :       maybe_warn_nonstring_arg (fndecl, exp);
    4482                 :          0 :       return ret;
    4483                 :            :     }
    4484                 :            : 
    4485                 :            :   return NULL_RTX;
    4486                 :            : }
    4487                 :            : 
    4488                 :            : /* Helper function to do the actual work for expand_builtin_strcpy.  The
    4489                 :            :    arguments to the builtin_strcpy call DEST and SRC are broken out
    4490                 :            :    so that this can also be called without constructing an actual CALL_EXPR.
    4491                 :            :    The other arguments and return value are the same as for
    4492                 :            :    expand_builtin_strcpy.  */
    4493                 :            : 
    4494                 :            : static rtx
    4495                 :       1128 : expand_builtin_strcpy_args (tree exp, tree dest, tree src, rtx target)
    4496                 :            : {
    4497                 :            :   /* Detect strcpy calls with unterminated arrays..  */
    4498                 :       1128 :   if (tree nonstr = unterminated_array (src))
    4499                 :            :     {
    4500                 :            :       /* NONSTR refers to the non-nul terminated constant array.  */
    4501                 :         69 :       if (!TREE_NO_WARNING (exp))
    4502                 :         16 :         warn_string_no_nul (EXPR_LOCATION (exp), "strcpy", src, nonstr);
    4503                 :         69 :       return NULL_RTX;
    4504                 :            :     }
    4505                 :            : 
    4506                 :       1059 :   return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
    4507                 :            : }
    4508                 :            : 
    4509                 :            : /* Expand a call EXP to the stpcpy builtin.
    4510                 :            :    Return NULL_RTX if we failed the caller should emit a normal call,
    4511                 :            :    otherwise try to get the result in TARGET, if convenient (and in
    4512                 :            :    mode MODE if that's convenient).  */
    4513                 :            : 
    4514                 :            : static rtx
    4515                 :        509 : expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
    4516                 :            : {
    4517                 :        509 :   tree dst, src;
    4518                 :        509 :   location_t loc = EXPR_LOCATION (exp);
    4519                 :            : 
    4520                 :        509 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    4521                 :            :     return NULL_RTX;
    4522                 :            : 
    4523                 :        500 :   dst = CALL_EXPR_ARG (exp, 0);
    4524                 :        500 :   src = CALL_EXPR_ARG (exp, 1);
    4525                 :            : 
    4526                 :        500 :   if (warn_stringop_overflow)
    4527                 :            :     {
    4528                 :        500 :       tree destsize = compute_objsize (dst, warn_stringop_overflow - 1);
    4529                 :        500 :       check_access (exp, dst, src, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE,
    4530                 :            :                     src, destsize);
    4531                 :            :     }
    4532                 :            : 
    4533                 :            :   /* If return value is ignored, transform stpcpy into strcpy.  */
    4534                 :        500 :   if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
    4535                 :            :     {
    4536                 :          0 :       tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
    4537                 :          0 :       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
    4538                 :          0 :       return expand_expr (result, target, mode, EXPAND_NORMAL);
    4539                 :            :     }
    4540                 :            :   else
    4541                 :            :     {
    4542                 :        500 :       tree len, lenp1;
    4543                 :        500 :       rtx ret;
    4544                 :            : 
    4545                 :            :       /* Ensure we get an actual string whose length can be evaluated at
    4546                 :            :          compile-time, not an expression containing a string.  This is
    4547                 :            :          because the latter will potentially produce pessimized code
    4548                 :            :          when used to produce the return value.  */
    4549                 :        500 :       c_strlen_data lendata = { };
    4550                 :        500 :       if (!c_getstr (src, NULL)
    4551                 :        500 :           || !(len = c_strlen (src, 0, &lendata, 1)))
    4552                 :        477 :         return expand_movstr (dst, src, target,
    4553                 :        477 :                               /*retmode=*/ RETURN_END_MINUS_ONE);
    4554                 :            : 
    4555                 :         23 :       if (lendata.decl && !TREE_NO_WARNING (exp))
    4556                 :          0 :         warn_string_no_nul (EXPR_LOCATION (exp), "stpcpy", src, lendata.decl);
    4557                 :            : 
    4558                 :         23 :       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
    4559                 :         23 :       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
    4560                 :            :                                          target, exp,
    4561                 :            :                                          /*retmode=*/ RETURN_END_MINUS_ONE);
    4562                 :            : 
    4563                 :         23 :       if (ret)
    4564                 :            :         return ret;
    4565                 :            : 
    4566                 :          0 :       if (TREE_CODE (len) == INTEGER_CST)
    4567                 :            :         {
    4568                 :          0 :           rtx len_rtx = expand_normal (len);
    4569                 :            : 
    4570                 :          0 :           if (CONST_INT_P (len_rtx))
    4571                 :            :             {
    4572                 :          0 :               ret = expand_builtin_strcpy_args (exp, dst, src, target);
    4573                 :            : 
    4574                 :          0 :               if (ret)
    4575                 :            :                 {
    4576                 :          0 :                   if (! target)
    4577                 :            :                     {
    4578                 :          0 :                       if (mode != VOIDmode)
    4579                 :          0 :                         target = gen_reg_rtx (mode);
    4580                 :            :                       else
    4581                 :          0 :                         target = gen_reg_rtx (GET_MODE (ret));
    4582                 :            :                     }
    4583                 :          0 :                   if (GET_MODE (target) != GET_MODE (ret))
    4584                 :          0 :                     ret = gen_lowpart (GET_MODE (target), ret);
    4585                 :            : 
    4586                 :          0 :                   ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
    4587                 :          0 :                   ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
    4588                 :          0 :                   gcc_assert (ret);
    4589                 :            : 
    4590                 :            :                   return target;
    4591                 :            :                 }
    4592                 :            :             }
    4593                 :            :         }
    4594                 :            : 
    4595                 :          0 :       return expand_movstr (dst, src, target,
    4596                 :          0 :                             /*retmode=*/ RETURN_END_MINUS_ONE);
    4597                 :            :     }
    4598                 :            : }
    4599                 :            : 
    4600                 :            : /* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
    4601                 :            :    arguments while being careful to avoid duplicate warnings (which could
    4602                 :            :    be issued if the expander were to expand the call, resulting in it
    4603                 :            :    being emitted in expand_call().  */
    4604                 :            : 
    4605                 :            : static rtx
    4606                 :        509 : expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
    4607                 :            : {
    4608                 :        509 :   if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
    4609                 :            :     {
    4610                 :            :       /* The call has been successfully expanded.  Check for nonstring
    4611                 :            :          arguments and issue warnings as appropriate.  */
    4612                 :         23 :       maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    4613                 :         23 :       return ret;
    4614                 :            :     }
    4615                 :            : 
    4616                 :            :   return NULL_RTX;
    4617                 :            : }
    4618                 :            : 
    4619                 :            : /* Check a call EXP to the stpncpy built-in for validity.
    4620                 :            :    Return NULL_RTX on both success and failure.  */
    4621                 :            : 
    4622                 :            : static rtx
    4623                 :        628 : expand_builtin_stpncpy (tree exp, rtx)
    4624                 :            : {
    4625                 :        628 :   if (!validate_arglist (exp,
    4626                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
    4627                 :        628 :       || !warn_stringop_overflow)
    4628                 :            :     return NULL_RTX;
    4629                 :            : 
    4630                 :            :   /* The source and destination of the call.  */
    4631                 :        503 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4632                 :        503 :   tree src = CALL_EXPR_ARG (exp, 1);
    4633                 :            : 
    4634                 :            :   /* The exact number of bytes to write (not the maximum).  */
    4635                 :        503 :   tree len = CALL_EXPR_ARG (exp, 2);
    4636                 :        503 :   if (!check_nul_terminated_array (exp, src, len))
    4637                 :            :     return NULL_RTX;
    4638                 :            : 
    4639                 :            :   /* The size of the destination object.  */
    4640                 :        497 :   tree destsize = compute_objsize (dest, warn_stringop_overflow - 1);
    4641                 :            : 
    4642                 :        497 :   check_access (exp, dest, src, len, /*maxread=*/NULL_TREE, src, destsize);
    4643                 :            : 
    4644                 :        497 :   return NULL_RTX;
    4645                 :            : }
    4646                 :            : 
    4647                 :            : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4648                 :            :    bytes from constant string DATA + OFFSET and return it as target
    4649                 :            :    constant.  */
    4650                 :            : 
    4651                 :            : rtx
    4652                 :       8284 : builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
    4653                 :            :                           scalar_int_mode mode)
    4654                 :            : {
    4655                 :       8284 :   const char *str = (const char *) data;
    4656                 :            : 
    4657                 :       8284 :   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
    4658                 :        308 :     return const0_rtx;
    4659                 :            : 
    4660                 :       7976 :   return c_readstr (str + offset, mode);
    4661                 :            : }
    4662                 :            : 
    4663                 :            : /* Helper to check the sizes of sequences and the destination of calls
    4664                 :            :    to __builtin_strncat and __builtin___strncat_chk.  Returns true on
    4665                 :            :    success (no overflow or invalid sizes), false otherwise.  */
    4666                 :            : 
    4667                 :            : static bool
    4668                 :        123 : check_strncat_sizes (tree exp, tree objsize)
    4669                 :            : {
    4670                 :        123 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4671                 :        123 :   tree src = CALL_EXPR_ARG (exp, 1);
    4672                 :        123 :   tree maxread = CALL_EXPR_ARG (exp, 2);
    4673                 :            : 
    4674                 :            :   /* Try to determine the range of lengths that the source expression
    4675                 :            :      refers to.  */
    4676                 :        123 :   c_strlen_data lendata = { };
    4677                 :        123 :   get_range_strlen (src, &lendata, /* eltsize = */ 1);
    4678                 :            : 
    4679                 :            :   /* Try to verify that the destination is big enough for the shortest
    4680                 :            :      string.  */
    4681                 :            : 
    4682                 :        123 :   if (!objsize && warn_stringop_overflow)
    4683                 :            :     {
    4684                 :            :       /* If it hasn't been provided by __strncat_chk, try to determine
    4685                 :            :          the size of the destination object into which the source is
    4686                 :            :          being copied.  */
    4687                 :          0 :       objsize = compute_objsize (dest, warn_stringop_overflow - 1);
    4688                 :            :     }
    4689                 :            : 
    4690                 :            :   /* Add one for the terminating nul.  */
    4691                 :        123 :   tree srclen = (lendata.minlen
    4692                 :        123 :                  ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
    4693                 :            :                                 size_one_node)
    4694                 :        123 :                  : NULL_TREE);
    4695                 :            : 
    4696                 :            :   /* The strncat function copies at most MAXREAD bytes and always appends
    4697                 :            :      the terminating nul so the specified upper bound should never be equal
    4698                 :            :      to (or greater than) the size of the destination.  */
    4699                 :         70 :   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
    4700                 :        171 :       && tree_int_cst_equal (objsize, maxread))
    4701                 :            :     {
    4702                 :         23 :       location_t loc = tree_nonartificial_location (exp);
    4703                 :         23 :       loc = expansion_point_location_if_in_system_header (loc);
    4704                 :            : 
    4705                 :         23 :       warning_at (loc, OPT_Wstringop_overflow_,
    4706                 :            :                   "%K%qD specified bound %E equals destination size",
    4707                 :            :                   exp, get_callee_fndecl (exp), maxread);
    4708                 :            : 
    4709                 :         23 :       return false;
    4710                 :            :     }
    4711                 :            : 
    4712                 :        100 :   if (!srclen
    4713                 :        100 :       || (maxread && tree_fits_uhwi_p (maxread)
    4714                 :         47 :           && tree_fits_uhwi_p (srclen)
    4715                 :         47 :           && tree_int_cst_lt (maxread, srclen)))
    4716                 :            :     srclen = maxread;
    4717                 :            : 
    4718                 :            :   /* The number of bytes to write is LEN but check_access will also
    4719                 :            :      check SRCLEN if LEN's value isn't known.  */
    4720                 :        100 :   return check_access (exp, dest, src, /*size=*/NULL_TREE, maxread, srclen,
    4721                 :        100 :                        objsize);
    4722                 :            : }
    4723                 :            : 
    4724                 :            : /* Similar to expand_builtin_strcat, do some very basic size validation
    4725                 :            :    of a call to the strcpy builtin given by EXP.  Return NULL_RTX to have
    4726                 :            :    the built-in expand to a call to the library function.  */
    4727                 :            : 
    4728                 :            : static rtx
    4729                 :        719 : expand_builtin_strncat (tree exp, rtx)
    4730                 :            : {
    4731                 :        719 :   if (!validate_arglist (exp,
    4732                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
    4733                 :        719 :       || !warn_stringop_overflow)
    4734                 :            :     return NULL_RTX;
    4735                 :            : 
    4736                 :        568 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4737                 :        568 :   tree src = CALL_EXPR_ARG (exp, 1);
    4738                 :            :   /* The upper bound on the number of bytes to write.  */
    4739                 :        568 :   tree maxread = CALL_EXPR_ARG (exp, 2);
    4740                 :            : 
    4741                 :            :   /* Detect unterminated source (only).  */
    4742                 :        568 :   if (!check_nul_terminated_array (exp, src, maxread))
    4743                 :            :     return NULL_RTX;
    4744                 :            : 
    4745                 :            :   /* The length of the source sequence.  */
    4746                 :        563 :   tree slen = c_strlen (src, 1);
    4747                 :            : 
    4748                 :            :   /* Try to determine the range of lengths that the source expression
    4749                 :            :      refers to.  Since the lengths are only used for warning and not
    4750                 :            :      for code generation disable strict mode below.  */
    4751                 :        563 :   tree maxlen = slen;
    4752                 :        563 :   if (!maxlen)
    4753                 :            :     {
    4754                 :        524 :       c_strlen_data lendata = { };
    4755                 :        524 :       get_range_strlen (src, &lendata, /* eltsize = */ 1);
    4756                 :        524 :       maxlen = lendata.maxbound;
    4757                 :            :     }
    4758                 :            : 
    4759                 :            :   /* Try to verify that the destination is big enough for the shortest
    4760                 :            :      string.  First try to determine the size of the destination object
    4761                 :            :      into which the source is being copied.  */
    4762                 :        563 :   tree destsize = compute_objsize (dest, warn_stringop_overflow - 1);
    4763                 :            : 
    4764                 :            :   /* Add one for the terminating nul.  */
    4765                 :        563 :   tree srclen = (maxlen
    4766                 :        563 :                  ? fold_build2 (PLUS_EXPR, size_type_node, maxlen,
    4767                 :            :                                 size_one_node)
    4768                 :        563 :                  : NULL_TREE);
    4769                 :            : 
    4770                 :            :   /* The strncat function copies at most MAXREAD bytes and always appends
    4771                 :            :      the terminating nul so the specified upper bound should never be equal
    4772                 :            :      to (or greater than) the size of the destination.  */
    4773                 :        199 :   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
    4774                 :        609 :       && tree_int_cst_equal (destsize, maxread))
    4775                 :            :     {
    4776                 :          7 :       location_t loc = tree_nonartificial_location (exp);
    4777                 :          7 :       loc = expansion_point_location_if_in_system_header (loc);
    4778                 :            : 
    4779                 :          7 :       warning_at (loc, OPT_Wstringop_overflow_,
    4780                 :            :                   "%K%qD specified bound %E equals destination size",
    4781                 :            :                   exp, get_callee_fndecl (exp), maxread);
    4782                 :            : 
    4783                 :          7 :       return NULL_RTX;
    4784                 :            :     }
    4785                 :            : 
    4786                 :        556 :   if (!srclen
    4787                 :        556 :       || (maxread && tree_fits_uhwi_p (maxread)
    4788                 :        139 :           && tree_fits_uhwi_p (srclen)
    4789                 :        139 :           && tree_int_cst_lt (maxread, srclen)))
    4790                 :            :     srclen = maxread;
    4791                 :            : 
    4792                 :            :   /* The number of bytes to write is SRCLEN.  */
    4793                 :        556 :   check_access (exp, dest, src, NULL_TREE, maxread, srclen, destsize);
    4794                 :            : 
    4795                 :        556 :   return NULL_RTX;
    4796                 :            : }
    4797                 :            : 
    4798                 :            : /* Expand expression EXP, which is a call to the strncpy builtin.  Return
    4799                 :            :    NULL_RTX if we failed the caller should emit a normal call.  */
    4800                 :            : 
    4801                 :            : static rtx
    4802                 :       1970 : expand_builtin_strncpy (tree exp, rtx target)
    4803                 :            : {
    4804                 :       1970 :   location_t loc = EXPR_LOCATION (exp);
    4805                 :            : 
    4806                 :       1970 :   if (!validate_arglist (exp,
    4807                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4808                 :            :     return NULL_RTX;
    4809                 :       1951 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4810                 :       1951 :   tree src = CALL_EXPR_ARG (exp, 1);
    4811                 :            :   /* The number of bytes to write (not the maximum).  */
    4812                 :       1951 :   tree len = CALL_EXPR_ARG (exp, 2);
    4813                 :            : 
    4814                 :       1951 :   if (!check_nul_terminated_array (exp, src, len))
    4815                 :            :     return NULL_RTX;
    4816                 :            : 
    4817                 :            :   /* The length of the source sequence.  */
    4818                 :       1948 :   tree slen = c_strlen (src, 1);
    4819                 :            : 
    4820                 :       1948 :   if (warn_stringop_overflow)
    4821                 :            :     {
    4822                 :       1557 :       tree destsize = compute_objsize (dest,
    4823                 :            :                                        warn_stringop_overflow - 1);
    4824                 :            : 
    4825                 :            :       /* The number of bytes to write is LEN but check_access will also
    4826                 :            :          check SLEN if LEN's value isn't known.  */
    4827                 :       1557 :       check_access (exp, dest, src, len, /*maxread=*/NULL_TREE, src,
    4828                 :            :                     destsize);
    4829                 :            :     }
    4830                 :            : 
    4831                 :            :   /* We must be passed a constant len and src parameter.  */
    4832                 :       1948 :   if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
    4833                 :            :     return NULL_RTX;
    4834                 :            : 
    4835                 :        155 :   slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
    4836                 :            : 
    4837                 :            :   /* We're required to pad with trailing zeros if the requested
    4838                 :            :      len is greater than strlen(s2)+1.  In that case try to
    4839                 :            :      use store_by_pieces, if it fails, punt.  */
    4840                 :        155 :   if (tree_int_cst_lt (slen, len))
    4841                 :            :     {
    4842                 :        147 :       unsigned int dest_align = get_pointer_alignment (dest);
    4843                 :        147 :       const char *p = c_getstr (src);
    4844                 :        147 :       rtx dest_mem;
    4845                 :            : 
    4846                 :        141 :       if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
    4847                 :        288 :           || !can_store_by_pieces (tree_to_uhwi (len),
    4848                 :            :                                    builtin_strncpy_read_str,
    4849                 :            :                                    CONST_CAST (char *, p),
    4850                 :            :                                    dest_align, false))
    4851                 :         16 :         return NULL_RTX;
    4852                 :            : 
    4853                 :        131 :       dest_mem = get_memory_rtx (dest, len);
    4854                 :        131 :       store_by_pieces (dest_mem, tree_to_uhwi (len),
    4855                 :            :                        builtin_strncpy_read_str,
    4856                 :            :                        CONST_CAST (char *, p), dest_align, false,
    4857                 :            :                        RETURN_BEGIN);
    4858                 :        131 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    4859                 :        131 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4860                 :        131 :       return dest_mem;
    4861                 :            :     }
    4862                 :            : 
    4863                 :            :   return NULL_RTX;
    4864                 :            : }
    4865                 :            : 
    4866                 :            : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4867                 :            :    bytes from constant string DATA + OFFSET and return it as target
    4868                 :            :    constant.  */
    4869                 :            : 
    4870                 :            : rtx
    4871                 :      32740 : builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4872                 :            :                          scalar_int_mode mode)
    4873                 :            : {
    4874                 :      32740 :   const char *c = (const char *) data;
    4875                 :      32740 :   char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
    4876                 :            : 
    4877                 :      32740 :   memset (p, *c, GET_MODE_SIZE (mode));
    4878                 :            : 
    4879                 :      32740 :   return c_readstr (p, mode);
    4880                 :            : }
    4881                 :            : 
    4882                 :            : /* Callback routine for store_by_pieces.  Return the RTL of a register
    4883                 :            :    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
    4884                 :            :    char value given in the RTL register data.  For example, if mode is
    4885                 :            :    4 bytes wide, return the RTL for 0x01010101*data.  */
    4886                 :            : 
    4887                 :            : static rtx
    4888                 :       1311 : builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4889                 :            :                         scalar_int_mode mode)
    4890                 :            : {
    4891                 :       1311 :   rtx target, coeff;
    4892                 :       1311 :   size_t size;
    4893                 :       1311 :   char *p;
    4894                 :            : 
    4895                 :       1311 :   size = GET_MODE_SIZE (mode);
    4896                 :       1311 :   if (size == 1)
    4897                 :            :     return (rtx) data;
    4898                 :            : 
    4899                 :       1037 :   p = XALLOCAVEC (char, size);
    4900                 :       1037 :   memset (p, 1, size);
    4901                 :       1037 :   coeff = c_readstr (p, mode);
    4902                 :            : 
    4903                 :       1037 :   target = convert_to_mode (mode, (rtx) data, 1);
    4904                 :       1037 :   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
    4905                 :       1037 :   return force_reg (mode, target);
    4906                 :            : }
    4907                 :            : 
    4908                 :            : /* Expand expression EXP, which is a call to the memset builtin.  Return
    4909                 :            :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    4910                 :            :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    4911                 :            :    convenient).  */
    4912                 :            : 
    4913                 :            : static rtx
    4914                 :      23563 : expand_builtin_memset (tree exp, rtx target, machine_mode mode)
    4915                 :            : {
    4916                 :      23563 :   if (!validate_arglist (exp,
    4917                 :            :                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4918                 :            :     return NULL_RTX;
    4919                 :            : 
    4920                 :      23551 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4921                 :      23551 :   tree val = CALL_EXPR_ARG (exp, 1);
    4922                 :      23551 :   tree len = CALL_EXPR_ARG (exp, 2);
    4923                 :            : 
    4924                 :      23551 :   check_memop_access (exp, dest, NULL_TREE, len);
    4925                 :            : 
    4926                 :      23551 :   return expand_builtin_memset_args (dest, val, len, target, mode, exp);
    4927                 :            : }
    4928                 :            : 
    4929                 :            : /* Helper function to do the actual work for expand_builtin_memset.  The
    4930                 :            :    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
    4931                 :            :    so that this can also be called without constructing an actual CALL_EXPR.
    4932                 :            :    The other arguments and return value are the same as for
    4933                 :            :    expand_builtin_memset.  */
    4934                 :            : 
    4935                 :            : static rtx
    4936                 :      23551 : expand_builtin_memset_args (tree dest, tree val, tree len,
    4937                 :            :                             rtx target, machine_mode mode, tree orig_exp)
    4938                 :            : {
    4939                 :      23551 :   tree fndecl, fn;
    4940                 :      23551 :   enum built_in_function fcode;
    4941                 :      23551 :   machine_mode val_mode;
    4942                 :      23551 :   char c;
    4943                 :      23551 :   unsigned int dest_align;
    4944                 :      23551 :   rtx dest_mem, dest_addr, len_rtx;
    4945                 :      23551 :   HOST_WIDE_INT expected_size = -1;
    4946                 :      23551 :   unsigned int expected_align = 0;
    4947                 :      23551 :   unsigned HOST_WIDE_INT min_size;
    4948                 :      23551 :   unsigned HOST_WIDE_INT max_size;
    4949                 :      23551 :   unsigned HOST_WIDE_INT probable_max_size;
    4950                 :            : 
    4951                 :      23551 :   dest_align = get_pointer_alignment (dest);
    4952                 :            : 
    4953                 :            :   /* If DEST is not a pointer type, don't do this operation in-line.  */
    4954                 :      23551 :   if (dest_align == 0)
    4955                 :            :     return NULL_RTX;
    4956                 :            : 
    4957                 :      23551 :   if (currently_expanding_gimple_stmt)
    4958                 :      23551 :     stringop_block_profile (currently_expanding_gimple_stmt,
    4959                 :            :                             &expected_align, &expected_size);
    4960                 :            : 
    4961                 :      23551 :   if (expected_align < dest_align)
    4962                 :      23546 :     expected_align = dest_align;
    4963                 :            : 
    4964                 :            :   /* If the LEN parameter is zero, return DEST.  */
    4965                 :      23551 :   if (integer_zerop (len))
    4966                 :            :     {
    4967                 :            :       /* Evaluate and ignore VAL in case it has side-effects.  */
    4968                 :          0 :       expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
    4969                 :          0 :       return expand_expr (dest, target, mode, EXPAND_NORMAL);
    4970                 :            :     }
    4971                 :            : 
    4972                 :            :   /* Stabilize the arguments in case we fail.  */
    4973                 :      23551 :   dest = builtin_save_expr (dest);
    4974                 :      23551 :   val = builtin_save_expr (val);
    4975                 :      23551 :   len = builtin_save_expr (len);
    4976                 :            : 
    4977                 :      23551 :   len_rtx = expand_normal (len);
    4978                 :      23551 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    4979                 :            :                         &probable_max_size);
    4980                 :      23551 :   dest_mem = get_memory_rtx (dest, len);
    4981                 :      23551 :   val_mode = TYPE_MODE (unsigned_char_type_node);
    4982                 :            : 
    4983                 :      23551 :   if (TREE_CODE (val) != INTEGER_CST)
    4984                 :            :     {
    4985                 :       1006 :       rtx val_rtx;
    4986                 :            : 
    4987                 :       1006 :       val_rtx = expand_normal (val);
    4988                 :       1006 :       val_rtx = convert_to_mode (val_mode, val_rtx, 0);
    4989                 :            : 
    4990                 :            :       /* Assume that we can memset by pieces if we can store
    4991                 :            :        * the coefficients by pieces (in the required modes).
    4992                 :            :        * We can't pass builtin_memset_gen_str as that emits RTL.  */
    4993                 :       1006 :       c = 1;
    4994                 :       1006 :       if (tree_fits_uhwi_p (len)
    4995                 :       1006 :           && can_store_by_pieces (tree_to_uhwi (len),
    4996                 :            :                                   builtin_memset_read_str, &c, dest_align,
    4997                 :            :                                   true))
    4998                 :            :         {
    4999                 :        607 :           val_rtx = force_reg (val_mode, val_rtx);
    5000                 :        607 :           store_by_pieces (dest_mem, tree_to_uhwi (len),
    5001                 :            :                            builtin_memset_gen_str, val_rtx, dest_align,
    5002                 :            :                            true, RETURN_BEGIN);
    5003                 :            :         }
    5004                 :        399 :       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
    5005                 :            :                                         dest_align, expected_align,
    5006                 :            :                                         expected_size, min_size, max_size,
    5007                 :            :                                         probable_max_size))
    5008                 :        251 :         goto do_libcall;
    5009                 :            : 
    5010                 :        755 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    5011                 :        755 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    5012                 :        755 :       return dest_mem;
    5013                 :            :     }
    5014                 :            : 
    5015                 :      22545 :   if (target_char_cast (val, &c))
    5016                 :            :     goto do_libcall;
    5017                 :            : 
    5018                 :      22545 :   if (c)
    5019                 :            :     {
    5020                 :       8657 :       if (tree_fits_uhwi_p (len)
    5021                 :       8657 :           && can_store_by_pieces (tree_to_uhwi (len),
    5022                 :            :                                   builtin_memset_read_str, &c, dest_align,
    5023                 :            :                                   true))
    5024                 :       4086 :         store_by_pieces (dest_mem, tree_to_uhwi (len),
    5025                 :            :                          builtin_memset_read_str, &c, dest_align, true,
    5026                 :            :                          RETURN_BEGIN);
    5027                 :       4571 :       else if (!set_storage_via_setmem (dest_mem, len_rtx,
    5028                 :            :                                         gen_int_mode (c, val_mode),
    5029                 :            :                                         dest_align, expected_align,
    5030                 :            :                                         expected_size, min_size, max_size,
    5031                 :            :                                         probable_max_size))
    5032                 :       3099 :         goto do_libcall;
    5033                 :            : 
    5034                 :       5558 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    5035                 :       5558 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    5036                 :       5558 :       return dest_mem;
    5037                 :            :     }
    5038                 :            : 
    5039                 :      13888 :   set_mem_align (dest_mem, dest_align);
    5040                 :      27776 :   dest_addr = clear_storage_hints (dest_mem, len_rtx,
    5041                 :      13888 :                                    CALL_EXPR_TAILCALL (orig_exp)
    5042                 :      13888 :                                    ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
    5043                 :            :                                    expected_align, expected_size,
    5044                 :            :                                    min_size, max_size,
    5045                 :            :                                    probable_max_size);
    5046                 :            : 
    5047                 :      13888 :   if (dest_addr == 0)
    5048                 :            :     {
    5049                 :       9380 :       dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    5050                 :       9380 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    5051                 :            :     }
    5052                 :            : 
    5053                 :            :   return dest_addr;
    5054                 :            : 
    5055                 :       3350 :  do_libcall:
    5056                 :       3350 :   fndecl = get_callee_fndecl (orig_exp);
    5057                 :       3350 :   fcode = DECL_FUNCTION_CODE (fndecl);
    5058                 :       3350 :   if (fcode == BUILT_IN_MEMSET)
    5059                 :       3350 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
    5060                 :            :                                 dest, val, len);
    5061                 :          0 :   else if (fcode == BUILT_IN_BZERO)
    5062                 :          0 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
    5063                 :            :                                 dest, len);
    5064                 :            :   else
    5065                 :          0 :     gcc_unreachable ();
    5066                 :       3350 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    5067                 :       3350 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
    5068                 :       3350 :   return expand_call (fn, target, target == const0_rtx);
    5069                 :            : }
    5070                 :            : 
    5071                 :            : /* Expand expression EXP, which is a call to the bzero builtin.  Return
    5072                 :            :    NULL_RTX if we failed the caller should emit a normal call.  */
    5073                 :            : 
    5074                 :            : static rtx
    5075                 :          0 : expand_builtin_bzero (tree exp)
    5076                 :            : {
    5077                 :          0 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    5078                 :            :     return NULL_RTX;
    5079                 :            : 
    5080                 :          0 :   tree dest = CALL_EXPR_ARG (exp, 0);
    5081                 :          0 :   tree size = CALL_EXPR_ARG (exp, 1);
    5082                 :            : 
    5083                 :          0 :   check_memop_access (exp, dest, NULL_TREE, size);
    5084                 :            : 
    5085                 :            :   /* New argument list transforming bzero(ptr x, int y) to
    5086                 :            :      memset(ptr x, int 0, size_t y).   This is done this way
    5087                 :            :      so that if it isn't expanded inline, we fallback to
    5088                 :            :      calling bzero instead of memset.  */
    5089                 :            : 
    5090                 :          0 :   location_t loc = EXPR_LOCATION (exp);
    5091                 :            : 
    5092                 :          0 :   return expand_builtin_memset_args (dest, integer_zero_node,
    5093                 :            :                                      fold_convert_loc (loc,
    5094                 :            :                                                        size_type_node, size),
    5095                 :          0 :                                      const0_rtx, VOIDmode, exp);
    5096                 :            : }
    5097                 :            : 
    5098                 :            : /* Try to expand cmpstr operation ICODE with the given operands.
    5099                 :            :    Return the result rtx on success, otherwise return null.  */
    5100                 :            : 
    5101                 :            : static rtx
    5102                 :          0 : expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
    5103                 :            :                HOST_WIDE_INT align)
    5104                 :            : {
    5105                 :          0 :   machine_mode insn_mode = insn_data[icode].operand[0].mode;
    5106                 :            : 
    5107                 :          0 :   if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
    5108                 :            :     target = NULL_RTX;
    5109                 :            : 
    5110                 :          0 :   class expand_operand ops[4];
    5111                 :          0 :   create_output_operand (&ops[0], target, insn_mode);
    5112                 :          0 :   create_fixed_operand (&ops[1], arg1_rtx);
    5113                 :          0 :   create_fixed_operand (&ops[2], arg2_rtx);
    5114                 :          0 :   create_integer_operand (&ops[3], align);
    5115                 :          0 :   if (maybe_expand_insn (icode, 4, ops))
    5116                 :          0 :     return ops[0].value;
    5117                 :            :   return NULL_RTX;
    5118                 :            : }
    5119                 :            : 
    5120                 :            : /* Expand expression EXP, which is a call to the memcmp built-in function.
    5121                 :            :    Return NULL_RTX if we failed and the caller should emit a normal call,
    5122                 :            :    otherwise try to get the result in TARGET, if convenient.
    5123                 :            :    RESULT_EQ is true if we can relax the returned value to be either zero
    5124                 :            :    or nonzero, without caring about the sign.  */
    5125                 :            : 
    5126                 :            : static rtx
    5127                 :      75215 : expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
    5128                 :            : {
    5129                 :      75215 :   if (!validate_arglist (exp,
    5130                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    5131                 :            :     return NULL_RTX;
    5132                 :            : 
    5133                 :      75205 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    5134                 :      75205 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    5135                 :      75205 :   tree len = CALL_EXPR_ARG (exp, 2);
    5136                 :      75205 :   enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
    5137                 :      75205 :   bool no_overflow = true;
    5138                 :            : 
    5139                 :            :   /* Diagnose calls where the specified length exceeds the size of either
    5140                 :            :      object.  */
    5141                 :      75205 :   tree size = compute_objsize (arg1, 0);
    5142                 :      75205 :   no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE,
    5143                 :            :                               len, /*maxread=*/NULL_TREE, size,
    5144                 :            :                               /*objsize=*/NULL_TREE);
    5145                 :      75205 :   if (no_overflow)
    5146                 :            :     {
    5147                 :      75175 :       size = compute_objsize (arg2, 0);
    5148                 :      75175 :       no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE,
    5149                 :            :                                   len,  /*maxread=*/NULL_TREE, size,
    5150                 :            :                                   /*objsize=*/NULL_TREE);
    5151                 :            :     }
    5152                 :            : 
    5153                 :            :   /* If the specified length exceeds the size of either object, 
    5154                 :            :      call the function.  */
    5155                 :      75205 :   if (!no_overflow)
    5156                 :            :     return NULL_RTX;
    5157                 :            : 
    5158                 :            :   /* Due to the performance benefit, always inline the calls first
    5159                 :            :      when result_eq is false.  */
    5160                 :      75147 :   rtx result = NULL_RTX;
    5161                 :            : 
    5162                 :      75147 :   if (!result_eq && fcode != BUILT_IN_BCMP)
    5163                 :            :     {
    5164                 :      63403 :       result = inline_expand_builtin_string_cmp (exp, target);
    5165                 :      63403 :       if (result)
    5166                 :            :         return result;
    5167                 :            :     }
    5168                 :            : 
    5169                 :      71589 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    5170                 :      71589 :   location_t loc = EXPR_LOCATION (exp);
    5171                 :            : 
    5172                 :      71589 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    5173                 :      71589 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    5174                 :            : 
    5175                 :            :   /* If we don't have POINTER_TYPE, call the function.  */
    5176                 :      71589 :   if (arg1_align == 0 || arg2_align == 0)
    5177                 :            :     return NULL_RTX;
    5178                 :            : 
    5179                 :      71589 :   rtx arg1_rtx = get_memory_rtx (arg1, len);
    5180                 :      71589 :   rtx arg2_rtx = get_memory_rtx (arg2, len);
    5181                 :      71589 :   rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
    5182                 :            : 
    5183                 :            :   /* Set MEM_SIZE as appropriate.  */
    5184                 :      71589 :   if (CONST_INT_P (len_rtx))
    5185                 :            :     {
    5186                 :      55074 :       set_mem_size (arg1_rtx, INTVAL (len_rtx));
    5187                 :      55074 :       set_mem_size (arg2_rtx, INTVAL (len_rtx));
    5188                 :            :     }
    5189                 :            : 
    5190                 :      71589 :   by_pieces_constfn constfn = NULL;
    5191                 :            : 
    5192                 :      71589 :   const char *src_str = c_getstr (arg2);
    5193                 :      71589 :   if (result_eq && src_str == NULL)
    5194                 :            :     {
    5195                 :      10106 :       src_str = c_getstr (arg1);
    5196                 :      10106 :       if (src_str != NULL)
    5197                 :         61 :         std::swap (arg1_rtx, arg2_rtx);
    5198                 :            :     }
    5199                 :            : 
    5200                 :            :   /* If SRC is a string constant and block move would be done
    5201                 :            :      by pieces, we can avoid loading the string from memory
    5202                 :            :      and only stored the computed constants.  */
    5203                 :      71589 :   if (src_str
    5204                 :       2627 :       && CONST_INT_P (len_rtx)
    5205                 :       2606 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1)
    5206                 :       1041 :     constfn = builtin_memcpy_read_str;
    5207                 :            : 
    5208                 :      71589 :   result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
    5209                 :      71589 :                                  TREE_TYPE (len), target,
    5210                 :            :                                  result_eq, constfn,
    5211                 :            :                                  CONST_CAST (char *, src_str));
    5212                 :            : 
    5213                 :      71589 :   if (result)
    5214                 :            :     {
    5215                 :            :       /* Return the value in the proper mode for this function.  */
    5216                 :       8027 :       if (GET_MODE (result) == mode)
    5217                 :            :         return result;
    5218                 :            : 
    5219                 :          5 :       if (target != 0)
    5220                 :            :         {
    5221                 :          5 :           convert_move (target, result, 0);
    5222                 :          5 :           return target;
    5223                 :            :         }
    5224                 :            : 
    5225                 :          0 :       return convert_to_mode (mode, result, 0);
    5226                 :            :     }
    5227                 :            : 
    5228                 :            :   return NULL_RTX;
    5229                 :            : }
    5230                 :            : 
    5231                 :            : /* Expand expression EXP, which is a call to the strcmp builtin.  Return NULL_RTX
    5232                 :            :    if we failed the caller should emit a normal call, otherwise try to get
    5233                 :            :    the result in TARGET, if convenient.  */
    5234                 :            : 
    5235                 :            : static rtx
    5236                 :       2796 : expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
    5237                 :            : {
    5238                 :       2796 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    5239                 :            :     return NULL_RTX;
    5240                 :            : 
    5241                 :       2790 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    5242                 :       2790 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    5243                 :            : 
    5244                 :       2790 :   if (!check_nul_terminated_array (exp, arg1)
    5245                 :       2790 :       || !check_nul_terminated_array (exp, arg2))
    5246                 :          5 :     return NULL_RTX;
    5247                 :            : 
    5248                 :            :   /* Due to the performance benefit, always inline the calls first.  */
    5249                 :       2785 :   rtx result = NULL_RTX;
    5250                 :       2785 :   result = inline_expand_builtin_string_cmp (exp, target);
    5251                 :       2785 :   if (result)
    5252                 :            :     return result;
    5253                 :            : 
    5254                 :       2400 :   insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
    5255                 :       2400 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    5256                 :       2400 :   if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
    5257                 :            :     return NULL_RTX;
    5258                 :            : 
    5259                 :       2400 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    5260                 :       2400 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    5261                 :            : 
    5262                 :            :   /* If we don't have POINTER_TYPE, call the function.  */
    5263                 :       2400 :   if (arg1_align == 0 || arg2_align == 0)
    5264                 :            :     return NULL_RTX;
    5265                 :            : 
    5266                 :            :   /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
    5267                 :       2400 :   arg1 = builtin_save_expr (arg1);
    5268                 :       2400 :   arg2 = builtin_save_expr (arg2);
    5269                 :            : 
    5270                 :       2400 :   rtx arg1_rtx = get_memory_rtx (arg1, NULL);
    5271                 :       2400 :   rtx arg2_rtx = get_memory_rtx (arg2, NULL);
    5272                 :            : 
    5273                 :            :   /* Try to call cmpstrsi.  */
    5274                 :       2400 :   if (cmpstr_icode != CODE_FOR_nothing)
    5275                 :          0 :     result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
    5276                 :          0 :                             MIN (arg1_align, arg2_align));
    5277                 :            : 
    5278                 :            :   /* Try to determine at least one length and call cmpstrnsi.  */
    5279                 :       2400 :   if (!result && cmpstrn_icode != CODE_FOR_nothing)
    5280                 :            :     {
    5281                 :       2400 :       tree len;
    5282                 :       2400 :       rtx arg3_rtx;
    5283                 :            : 
    5284                 :       2400 :       tree len1 = c_strlen (arg1, 1);
    5285                 :       2400 :       tree len2 = c_strlen (arg2, 1);
    5286                 :            : 
    5287                 :       2400 :       if (len1)
    5288                 :        205 :         len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
    5289                 :       2400 :       if (len2)
    5290                 :       1505 :         len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
    5291                 :            : 
    5292                 :            :       /* If we don't have a constant length for the first, use the length
    5293                 :            :          of the second, if we know it.  We don't require a constant for
    5294                 :            :          this case; some cost analysis could be done if both are available
    5295                 :            :          but neither is constant.  For now, assume they're equally cheap,
    5296                 :            :          unless one has side effects.  If both strings have constant lengths,
    5297                 :            :          use the smaller.  */
    5298                 :            : 
    5299                 :       2400 :       if (!len1)
    5300                 :            :         len = len2;
    5301                 :        205 :       else if (!len2)
    5302                 :            :         len = len1;
    5303                 :         12 :       else if (TREE_SIDE_EFFECTS (len1))
    5304                 :            :         len = len2;
    5305                 :         12 :       else if (TREE_SIDE_EFFECTS (len2))
    5306                 :            :         len = len1;
    5307                 :         12 :       else if (TREE_CODE (len1) != INTEGER_CST)
    5308                 :            :         len = len2;
    5309                 :         12 :       else if (TREE_CODE (len2) != INTEGER_CST)
    5310                 :            :         len = len1;
    5311                 :          5 :       else if (tree_int_cst_lt (len1, len2))
    5312                 :            :         len = len1;
    5313                 :            :       else
    5314                 :          5 :         len = len2;
    5315                 :            : 
    5316                 :            :       /* If both arguments have side effects, we cannot optimize.  */
    5317                 :       4098 :       if (len && !TREE_SIDE_EFFECTS (len))
    5318                 :            :         {
    5319                 :       1698 :           arg3_rtx = expand_normal (len);
    5320                 :       1698 :           result = expand_cmpstrn_or_cmpmem
    5321                 :       1698 :             (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
    5322                 :       1698 :              arg3_rtx, MIN (arg1_align, arg2_align));
    5323                 :            :         }
    5324                 :            :     }
    5325                 :            : 
    5326                 :       2400 :   tree fndecl = get_callee_fndecl (exp);
    5327                 :       2400 :   if (result)
    5328                 :            :     {
    5329                 :            :       /* Check to see if the argument was declared attribute nonstring
    5330                 :            :          and if so, issue a warning since at this point it's not known
    5331                 :            :          to be nul-terminated.  */
    5332                 :       1019 :       maybe_warn_nonstring_arg (fndecl, exp);
    5333                 :            : 
    5334                 :            :       /* Return the value in the proper mode for this function.  */
    5335                 :       1019 :       machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    5336                 :       1019 :       if (GET_MODE (result) == mode)
    5337                 :            :         return result;
    5338                 :          0 :       if (target == 0)
    5339                 :          0 :         return convert_to_mode (mode, result, 0);
    5340                 :          0 :       convert_move (target, result, 0);
    5341                 :          0 :       return target;
    5342                 :            :     }
    5343                 :            : 
    5344                 :            :   /* Expand the library call ourselves using a stabilized argument
    5345                 :            :      list to avoid re-evaluating the function's arguments twice.  */
    5346                 :       1381 :   tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
    5347                 :       1381 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    5348                 :       1381 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    5349                 :       1381 :   return expand_call (fn, target, target == const0_rtx);
    5350                 :            : }
    5351                 :            : 
    5352                 :            : /* Expand expression EXP, which is a call to the strncmp builtin. Return
    5353                 :            :    NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
    5354                 :            :    the result in TARGET, if convenient.  */
    5355                 :            : 
    5356                 :            : static rtx
    5357                 :       1123 : expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
    5358                 :            :                         ATTRIBUTE_UNUSED machine_mode mode)
    5359                 :            : {
    5360                 :       1123 :   if (!validate_arglist (exp,
    5361                 :            :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    5362                 :            :     return NULL_RTX;
    5363                 :            : 
    5364                 :       1117 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    5365                 :       1117 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    5366                 :       1117 :   tree arg3 = CALL_EXPR_ARG (exp, 2);
    5367                 :            : 
    5368                 :       1117 :   if (!check_nul_terminated_array (exp, arg1, arg3)
    5369                 :       1117 :       || !check_nul_terminated_array (exp, arg2, arg3))
    5370                 :          2 :     return NULL_RTX;
    5371                 :            : 
    5372                 :            :   /* Due to the performance benefit, always inline the calls first.  */
    5373                 :       1115 :   rtx result = NULL_RTX;
    5374                 :       1115 :   result = inline_expand_builtin_string_cmp (exp, target);
    5375                 :       1115 :   if (result)
    5376                 :            :     return result;
    5377                 :            : 
    5378                 :            :   /* If c_strlen can determine an expression for one of the string
    5379                 :            :      lengths, and it doesn't have side effects, then emit cmpstrnsi
    5380                 :            :      using length MIN(strlen(string)+1, arg3).  */
    5381                 :       1083 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    5382                 :       1083 :   if (cmpstrn_icode == CODE_FOR_nothing)
    5383                 :            :     return NULL_RTX;
    5384                 :            : 
    5385                 :       1083 :   tree len;
    5386                 :            : 
    5387                 :       1083 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    5388                 :       1083 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    5389                 :            : 
    5390                 :       1083 :   tree len1 = c_strlen (arg1, 1);
    5391                 :       1083 :   tree len2 = c_strlen (arg2, 1);
    5392                 :            : 
    5393                 :       1083 :   location_t loc = EXPR_LOCATION (exp);
    5394                 :            : 
    5395                 :       1083 :   if (len1)
    5396                 :        142 :     len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
    5397                 :       1083 :   if (len2)
    5398                 :        433 :     len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
    5399                 :            : 
    5400                 :       1083 :   tree len3 = fold_convert_loc (loc, sizetype, arg3);
    5401                 :            : 
    5402                 :            :   /* If we don't have a constant length for the first, use the length
    5403                 :            :      of the second, if we know it.  If neither string is constant length,
    5404                 :            :      use the given length argument.  We don't require a constant for
    5405                 :            :      this case; some cost analysis could be done if both are available
    5406                 :            :      but neither is constant.  For now, assume they're equally cheap,
    5407                 :            :      unless one has side effects.  If both strings have constant lengths,
    5408                 :            :      use the smaller.  */
    5409                 :            : 
    5410                 :       1083 :   if (!len1 && !len2)
    5411                 :            :     len = len3;
    5412                 :        458 :   else if (!len1)
    5413                 :            :     len = len2;
    5414                 :        142 :   else if (!len2)
    5415                 :            :     len = len1;
    5416                 :        117 :   else if (TREE_SIDE_EFFECTS (len1))
    5417                 :            :     len = len2;
    5418                 :        117 :   else if (TREE_SIDE_EFFECTS (len2))
    5419                 :            :     len = len1;
    5420                 :        117 :   else if (TREE_CODE (len1) != INTEGER_CST)
    5421                 :            :     len = len2;
    5422                 :        117 :   else if (TREE_CODE (len2) != INTEGER_CST)
    5423                 :            :     len = len1;
    5424                 :        117 :   else if (tree_int_cst_lt (len1, len2))
    5425                 :            :     len = len1;
    5426                 :            :   else
    5427                 :          1 :     len = len2;
    5428                 :            : 
    5429                 :            :   /* If we are not using the given length, we must incorporate it here.
    5430                 :            :      The actual new length parameter will be MIN(len,arg3) in this case.  */
    5431                 :       1083 :   if (len != len3)
    5432                 :            :     {
    5433                 :        458 :       len = fold_convert_loc (loc, sizetype, len);
    5434                 :        458 :       len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
    5435                 :            :     }
    5436                 :       1083 :   rtx arg1_rtx = get_memory_rtx (arg1, len);
    5437                 :       1083 :   rtx arg2_rtx = get_memory_rtx (arg2, len);
    5438                 :       1083 :   rtx arg3_rtx = expand_normal (len);
    5439                 :       3249 :   result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
    5440                 :       1083 :                                      arg2_rtx, TREE_TYPE (len), arg3_rtx,
    5441                 :       1083 :                                      MIN (arg1_align, arg2_align));
    5442                 :            : 
    5443                 :       1083 :   tree fndecl = get_callee_fndecl (exp);
    5444                 :       1083 :   if (result)
    5445                 :            :     {
    5446                 :            :       /* Check to see if the argument was declared attribute nonstring
    5447                 :            :          and if so, issue a warning since at this point it's not known
    5448                 :            :          to be nul-terminated.  */
    5449                 :        353 :       maybe_warn_nonstring_arg (fndecl, exp);
    5450                 :            : 
    5451                 :            :       /* Return the value in the proper mode for this function.  */
    5452                 :        353 :       mode = TYPE_MODE (TREE_TYPE (exp));
    5453                 :        353 :       if (GET_MODE (result) == mode)
    5454                 :            :         return result;
    5455                 :          0 :       if (target == 0)
    5456                 :          0 :         return convert_to_mode (mode, result, 0);
    5457                 :          0 :       convert_move (target, result, 0);
    5458                 :          0 :       return target;
    5459                 :            :     }
    5460                 :            : 
    5461                 :            :   /* Expand the library call ourselves using a stabilized argument
    5462                 :            :      list to avoid re-evaluating the function's arguments twice.  */
    5463                 :        730 :   tree fn = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
    5464                 :        730 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    5465                 :        730 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    5466                 :        730 :   return expand_call (fn, target, target == const0_rtx);
    5467                 :            : }
    5468                 :            : 
    5469                 :            : /* Expand a call to __builtin_saveregs, generating the result in TARGET,
    5470                 :            :    if that's convenient.  */
    5471                 :            : 
    5472                 :            : rtx
    5473                 :          0 : expand_builtin_saveregs (void)
    5474                 :            : {
    5475                 :          0 :   rtx val;
    5476                 :          0 :   rtx_insn *seq;
    5477                 :            : 
    5478                 :            :   /* Don't do __builtin_saveregs more than once in a function.
    5479                 :            :      Save the result of the first call and reuse it.  */
    5480                 :          0 :   if (saveregs_value != 0)
    5481                 :            :     return saveregs_value;
    5482                 :            : 
    5483                 :            :   /* When this function is called, it means that registers must be
    5484                 :            :      saved on entry to this function.  So we migrate the call to the
    5485                 :            :      first insn of this function.  */
    5486                 :            : 
    5487                 :          0 :   start_sequence ();
    5488                 :            : 
    5489                 :            :   /* Do whatever the machine needs done in this case.  */
    5490                 :          0 :   val = targetm.calls.expand_builtin_saveregs ();
    5491                 :            : 
    5492                 :          0 :   seq = get_insns ();
    5493                 :          0 :   end_sequence ();
    5494                 :            : 
    5495                 :          0 :   saveregs_value = val;
    5496                 :            : 
    5497                 :            :   /* Put the insns after the NOTE that starts the function.  If this
    5498                 :            :      is inside a start_sequence, make the outer-level insn chain current, so
    5499                 :            :      the code is placed at the start of the function.  */
    5500                 :          0 :   push_topmost_sequence ();
    5501                 :          0 :   emit_insn_after (seq, entry_of_function ());
    5502                 :          0 :   pop_topmost_sequence ();
    5503                 :            : 
    5504                 :          0 :   return val;
    5505                 :            : }
    5506                 :            : 
    5507                 :            : /* Expand a call to __builtin_next_arg.  */
    5508                 :            : 
    5509                 :            : static rtx
    5510                 :      15786 : expand_builtin_next_arg (void)
    5511                 :            : {
    5512                 :            :   /* Checking arguments is already done in fold_builtin_next_arg
    5513                 :            :      that must be called before this function.  */
    5514                 :      15786 :   return expand_binop (ptr_mode, add_optab,
    5515                 :            :                        crtl->args.internal_arg_pointer,
    5516                 :            :                        crtl->args.arg_offset_rtx,
    5517                 :      15786 :                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
    5518                 :            : }
    5519                 :            : 
    5520                 :            : /* Make it easier for the backends by protecting the valist argument
    5521                 :            :    from multiple evaluations.  */
    5522                 :            : 
    5523                 :            : static tree
    5524                 :      15978 : stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
    5525                 :            : {
    5526                 :      15978 :   tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
    5527                 :            : 
    5528                 :            :   /* The current way of determining the type of valist is completely
    5529                 :            :      bogus.  We should have the information on the va builtin instead.  */
    5530                 :      15978 :   if (!vatype)
    5531                 :      15873 :     vatype = targetm.fn_abi_va_list (cfun->decl);
    5532                 :            : 
    5533                 :      15978 :   if (TREE_CODE (vatype) == ARRAY_TYPE)
    5534                 :            :     {
    5535                 :      10322 :       if (TREE_SIDE_EFFECTS (valist))
    5536                 :          0 :         valist = save_expr (valist);
    5537                 :            : 
    5538                 :            :       /* For this case, the backends will be expecting a pointer to
    5539                 :            :          vatype, but it's possible we've actually been given an array
    5540                 :            :          (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
    5541                 :            :          So fix it.  */
    5542                 :      10322 :       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
    5543                 :            :         {
    5544                 :          0 :           tree p1 = build_pointer_type (TREE_TYPE (vatype));
    5545                 :          0 :           valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
    5546                 :            :         }
    5547                 :            :     }
    5548                 :            :   else
    5549                 :            :     {
    5550                 :       5656 :       tree pt = build_pointer_type (vatype);
    5551                 :            : 
    5552                 :       5656 :       if (! needs_lvalue)
    5553                 :            :         {
    5554                 :          0 :           if (! TREE_SIDE_EFFECTS (valist))
    5555                 :            :             return valist;
    5556                 :            : 
    5557                 :          0 :           valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
    5558                 :          0 :           TREE_SIDE_EFFECTS (valist) = 1;
    5559                 :            :         }
    5560                 :            : 
    5561                 :       5656 :       if (TREE_SIDE_EFFECTS (valist))
    5562                 :          0 :         valist = save_expr (valist);
    5563                 :       5656 :       valist = fold_build2_loc (loc, MEM_REF,
    5564                 :       5656 :                                 vatype, valist, build_int_cst (pt, 0));
    5565                 :            :     }
    5566                 :            : 
    5567                 :            :   return valist;
    5568                 :            : }
    5569                 :            : 
    5570                 :            : /* The "standard" definition of va_list is void*.  */
    5571                 :            : 
    5572                 :            : tree
    5573                 :          0 : std_build_builtin_va_list (void)
    5574                 :            : {
    5575                 :          0 :   return ptr_type_node;
    5576                 :            : }
    5577                 :            : 
    5578                 :            : /* The "standard" abi va_list is va_list_type_node.  */
    5579                 :            : 
    5580                 :            : tree
    5581                 :          0 : std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
    5582                 :            : {
    5583                 :          0 :   return va_list_type_node;
    5584                 :            : }
    5585                 :            : 
    5586                 :            : /* The "standard" type of va_list is va_list_type_node.  */
    5587                 :            : 
    5588                 :            : tree
    5589                 :        466 : std_canonical_va_list_type (tree type)
    5590                 :            : {
    5591                 :        466 :   tree wtype, htype;
    5592                 :            : 
    5593                 :        466 :   wtype = va_list_type_node;
    5594                 :        466 :   htype = type;
    5595                 :            : 
    5596                 :        466 :   if (TREE_CODE (wtype) == ARRAY_TYPE)
    5597                 :            :     {
    5598                 :            :       /* If va_list is an array type, the argument may have decayed
    5599                 :            :          to a pointer type, e.g. by being passed to another function.
    5600                 :            :          In that case, unwrap both types so that we can compare the
    5601                 :            :          underlying records.  */
    5602                 :          0 :       if (TREE_CODE (htype) == ARRAY_TYPE
    5603                 :          0 :           || POINTER_TYPE_P (htype))
    5604                 :            :         {
    5605                 :          0 :           wtype = TREE_TYPE (wtype);
    5606                 :          0 :           htype = TREE_TYPE (htype);
    5607                 :            :         }
    5608                 :            :     }
    5609                 :        466 :   if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
    5610                 :        308 :     return va_list_type_node;
    5611                 :            : 
    5612                 :            :   return NULL_TREE;
    5613                 :            : }
    5614                 :            : 
    5615                 :            : /* The "standard" implementation of va_start: just assign `nextarg' to
    5616                 :            :    the variable.  */
    5617                 :            : 
    5618                 :            : void
    5619                 :       5652 : std_expand_builtin_va_start (tree valist, rtx nextarg)
    5620                 :            : {
    5621                 :       5652 :   rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
    5622                 :       5652 :   convert_move (va_r, nextarg, 0);
    5623                 :       5652 : }
    5624                 :            : 
    5625                 :            : /* Expand EXP, a call to __builtin_va_start.  */
    5626                 :            : 
    5627                 :            : static rtx
    5628                 :      15658 : expand_builtin_va_start (tree exp)
    5629                 :            : {
    5630                 :      15658 :   rtx nextarg;
    5631                 :      15658 :   tree valist;
    5632                 :      15658 :   location_t loc = EXPR_LOCATION (exp);
    5633                 :            : 
    5634                 :      15658 :   if (call_expr_nargs (exp) < 2)
    5635                 :            :     {
    5636                 :          0 :       error_at (loc, "too few arguments to function %<va_start%>");
    5637                 :          0 :       return const0_rtx;
    5638                 :            :     }
    5639                 :            : 
    5640                 :      15658 :   if (fold_builtin_next_arg (exp, true))
    5641                 :          0 :     return const0_rtx;
    5642                 :            : 
    5643                 :      15658 :   nextarg = expand_builtin_next_arg ();
    5644                 :      15658 :   valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
    5645                 :            : 
    5646                 :      15658 :   if (targetm.expand_builtin_va_start)
    5647                 :      15658 :     targetm.expand_builtin_va_start (valist, nextarg);
    5648                 :            :   else
    5649                 :          0 :     std_expand_builtin_va_start (valist, nextarg);
    5650                 :            : 
    5651                 :      15658 :   return const0_rtx;
    5652                 :            : }
    5653                 :            : 
    5654                 :            : /* Expand EXP, a call to __builtin_va_end.  */
    5655                 :            : 
    5656                 :            : static rtx
    5657                 :       7507 : expand_builtin_va_end (tree exp)
    5658                 :            : {
    5659                 :       7507 :   tree valist = CALL_EXPR_ARG (exp, 0);
    5660                 :            : 
    5661                 :            :   /* Evaluate for side effects, if needed.  I hate macros that don't
    5662                 :            :      do that.  */
    5663                 :       7507 :   if (TREE_SIDE_EFFECTS (valist))
    5664                 :          0 :     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5665                 :            : 
    5666                 :       7507 :   return const0_rtx;
    5667                 :            : }
    5668                 :            : 
    5669                 :            : /* Expand EXP, a call to __builtin_va_copy.  We do this as a
    5670                 :            :    builtin rather than just as an assignment in stdarg.h because of the
    5671                 :            :    nastiness of array-type va_list types.  */
    5672                 :            : 
    5673                 :            : static rtx
    5674                 :        160 : expand_builtin_va_copy (tree exp)
    5675                 :            : {
    5676                 :        160 :   tree dst, src, t;
    5677                 :        160 :   location_t loc = EXPR_LOCATION (exp);
    5678                 :            : 
    5679                 :        160 :   dst = CALL_EXPR_ARG (exp, 0);
    5680                 :        160 :   src = CALL_EXPR_ARG (exp, 1);
    5681                 :            : 
    5682                 :        160 :   dst = stabilize_va_list_loc (loc, dst, 1);
    5683                 :        160 :   src = stabilize_va_list_loc (loc, src, 0);
    5684                 :            : 
    5685                 :        160 :   gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
    5686                 :            : 
    5687                 :        160 :   if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
    5688                 :            :     {
    5689                 :          0 :       t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
    5690                 :          0 :       TREE_SIDE_EFFECTS (t) = 1;
    5691                 :          0 :       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5692                 :            :     }
    5693                 :            :   else
    5694                 :            :     {
    5695                 :        160 :       rtx dstb, srcb, size;
    5696                 :            : 
    5697                 :            :       /* Evaluate to pointers.  */
    5698                 :        160 :       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
    5699                 :        160 :       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
    5700                 :        160 :       size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
    5701                 :            :                   NULL_RTX, VOIDmode, EXPAND_NORMAL);
    5702                 :            : 
    5703                 :        320 :       dstb = convert_memory_address (Pmode, dstb);
    5704                 :        320 :       srcb = convert_memory_address (Pmode, srcb);
    5705                 :            : 
    5706                 :            :       /* "Dereference" to BLKmode memories.  */
    5707                 :        160 :       dstb = gen_rtx_MEM (BLKmode, dstb);
    5708                 :        160 :       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
    5709                 :        160 :       set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5710                 :        160 :       srcb = gen_rtx_MEM (BLKmode, srcb);
    5711                 :        160 :       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
    5712                 :        160 :       set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5713                 :            : 
    5714                 :            :       /* Copy.  */
    5715                 :        160 :       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
    5716                 :            :     }
    5717                 :            : 
    5718                 :        160 :   return const0_rtx;
    5719                 :            : }
    5720                 :            : 
    5721                 :            : /* Expand a call to one of the builtin functions __builtin_frame_address or
    5722                 :            :    __builtin_return_address.  */
    5723                 :            : 
    5724                 :            : static rtx
    5725                 :      14219 : expand_builtin_frame_address (tree fndecl, tree exp)
    5726                 :            : {
    5727                 :            :   /* The argument must be a nonnegative integer constant.
    5728                 :            :      It counts the number of frames to scan up the stack.
    5729                 :            :      The value is either the frame pointer value or the return
    5730                 :            :      address saved in that frame.  */
    5731                 :      14219 :   if (call_expr_nargs (exp) == 0)
    5732                 :            :     /* Warning about missing arg was already issued.  */
    5733                 :          0 :     return const0_rtx;
    5734                 :      14219 :   else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
    5735                 :            :     {
    5736                 :          0 :       error ("invalid argument to %qD", fndecl);
    5737                 :          0 :       return const0_rtx;
    5738                 :            :     }
    5739                 :            :   else
    5740                 :            :     {
    5741                 :            :       /* Number of frames to scan up the stack.  */
    5742                 :      14219 :       unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
    5743                 :            : 
    5744                 :      14219 :       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
    5745                 :            : 
    5746                 :            :       /* Some ports cannot access arbitrary stack frames.  */
    5747                 :      14219 :       if (tem == NULL)
    5748                 :            :         {
    5749                 :          0 :           warning (0, "unsupported argument to %qD", fndecl);
    5750                 :          0 :           return const0_rtx;
    5751                 :            :         }
    5752                 :            : 
    5753                 :      14219 :       if (count)
    5754                 :            :         {
    5755                 :            :           /* Warn since no effort is made to ensure that any frame
    5756                 :            :              beyond the current one exists or can be safely reached.  */
    5757                 :        982 :           warning (OPT_Wframe_address, "calling %qD with "
    5758                 :            :                    "a nonzero argument is unsafe", fndecl);
    5759                 :            :         }
    5760                 :            : 
    5761                 :            :       /* For __builtin_frame_address, return what we've got.  */
    5762                 :      14219 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
    5763                 :            :         return tem;
    5764                 :            : 
    5765                 :       4717 :       if (!REG_P (tem)
    5766                 :       4717 :           && ! CONSTANT_P (tem))
    5767                 :       4717 :         tem = copy_addr_to_reg (tem);
    5768                 :       4717 :       return tem;
    5769                 :            :     }
    5770                 :            : }
    5771                 :            : 
    5772                 :            : /* Expand EXP, a call to the alloca builtin.  Return NULL_RTX if we
    5773                 :            :    failed and the caller should emit a normal call.  */
    5774                 :            : 
    5775                 :            : static rtx
    5776                 :      11480 : expand_builtin_alloca (tree exp)
    5777                 :            : {
    5778                 :      11480 :   rtx op0;
    5779                 :      11480 :   rtx result;
    5780                 :      11480 :   unsigned int align;
    5781                 :      11480 :   tree fndecl = get_callee_fndecl (exp);
    5782                 :      11480 :   HOST_WIDE_INT max_size;
    5783                 :      11480 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    5784                 :      11480 :   bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
    5785                 :      11480 :   bool valid_arglist
    5786                 :            :     = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5787                 :      22958 :        ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
    5788                 :            :                            VOID_TYPE)
    5789                 :            :        : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
    5790                 :      19957 :          ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
    5791                 :       8479 :          : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
    5792                 :            : 
    5793                 :      11480 :   if (!valid_arglist)
    5794                 :            :     return NULL_RTX;
    5795                 :            : 
    5796                 :      11475 :   if ((alloca_for_var
    5797                 :       1770 :        && warn_vla_limit >= HOST_WIDE_INT_MAX
    5798                 :       1757 :        && warn_alloc_size_limit < warn_vla_limit)
    5799                 :      11475 :       || (!alloca_for_var
    5800                 :       9705 :           && warn_alloca_limit >= HOST_WIDE_INT_MAX
    5801                 :       9668 :           && warn_alloc_size_limit < warn_alloca_limit
    5802                 :            :           ))
    5803                 :            :     {
    5804                 :            :       /* -Walloca-larger-than and -Wvla-larger-than settings of
    5805                 :            :          less than HOST_WIDE_INT_MAX override the more general
    5806                 :            :          -Walloc-size-larger-than so unless either of the former
    5807                 :            :          options is smaller than the last one (wchich would imply
    5808                 :            :          that the call was already checked), check the alloca
    5809                 :            :          arguments for overflow.  */
    5810                 :          8 :       tree args[] = { CALL_EXPR_ARG (exp, 0), NULL_TREE };
    5811                 :          8 :       int idx[] = { 0, -1 };
    5812                 :          8 :       maybe_warn_alloc_args_overflow (fndecl, exp, args, idx);
    5813                 :            :     }
    5814                 :            : 
    5815                 :            :   /* Compute the argument.  */
    5816                 :      11475 :   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    5817                 :            : 
    5818                 :            :   /* Compute the alignment.  */
    5819                 :      11475 :   align = (fcode == BUILT_IN_ALLOCA
    5820                 :       8474 :            ? BIGGEST_ALIGNMENT
    5821                 :       3001 :            : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
    5822                 :            : 
    5823                 :            :   /* Compute the maximum size.  */
    5824                 :      22950 :   max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5825                 :      11477 :               ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
    5826                 :            :               : -1);
    5827                 :            : 
    5828                 :            :   /* Allocate the desired space.  If the allocation stems from the declaration
    5829                 :            :      of a variable-sized object, it cannot accumulate.  */
    5830                 :      11475 :   result
    5831                 :      11475 :     = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
    5832                 :      11475 :   result = convert_memory_address (ptr_mode, result);
    5833                 :            : 
    5834                 :            :   /* Dynamic allocations for variables are recorded during gimplification.  */
    5835                 :      11475 :   if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
    5836                 :          0 :     record_dynamic_alloc (exp);
    5837                 :            : 
    5838                 :            :   return result;
    5839                 :            : }
    5840                 :            : 
    5841                 :            : /* Emit a call to __asan_allocas_unpoison call in EXP.  Add to second argument
    5842                 :            :    of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
    5843                 :            :    STACK_DYNAMIC_OFFSET value.  See motivation for this in comment to
    5844                 :            :    handle_builtin_stack_restore function.  */
    5845                 :            : 
    5846                 :            : static rtx
    5847                 :        180 : expand_asan_emit_allocas_unpoison (tree exp)
    5848                 :            : {
    5849                 :        180 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    5850                 :        180 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    5851                 :        180 :   rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5852                 :        180 :   rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5853                 :        180 :   rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
    5854                 :            :                                  stack_pointer_rtx, NULL_RTX, 0,
    5855                 :            :                                  OPTAB_LIB_WIDEN);
    5856                 :        180 :   off = convert_modes (ptr_mode, Pmode, off, 0);
    5857                 :        180 :   bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
    5858                 :            :                              OPTAB_LIB_WIDEN);
    5859                 :        180 :   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
    5860                 :        180 :   ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
    5861                 :            :                                  top, ptr_mode, bot, ptr_mode);
    5862                 :        180 :   return ret;
    5863                 :            : }
    5864                 :            : 
    5865                 :            : /* Expand a call to bswap builtin in EXP.
    5866                 :            :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5867                 :            :    function in-line.  If convenient, the result should be placed in TARGET.
    5868                 :            :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5869                 :            : 
    5870                 :            : static rtx
    5871                 :        893 : expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
    5872                 :            :                       rtx subtarget)
    5873                 :            : {
    5874                 :        893 :   tree arg;
    5875                 :        893 :   rtx op0;
    5876                 :            : 
    5877                 :        893 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5878                 :            :     return NULL_RTX;
    5879                 :            : 
    5880                 :        893 :   arg = CALL_EXPR_ARG (exp, 0);
    5881                 :        893 :   op0 = expand_expr (arg,
    5882                 :         28 :                      subtarget && GET_MODE (subtarget) == target_mode
    5883                 :            :                      ? subtarget : NULL_RTX,
    5884                 :            :                      target_mode, EXPAND_NORMAL);
    5885                 :        893 :   if (GET_MODE (op0) != target_mode)
    5886                 :         62 :     op0 = convert_to_mode (target_mode, op0, 1);
    5887                 :            : 
    5888                 :        893 :   target = expand_unop (target_mode, bswap_optab, op0, target, 1);
    5889                 :            : 
    5890                 :        893 :   gcc_assert (target);
    5891                 :            : 
    5892                 :        893 :   return convert_to_mode (target_mode, target, 1);
    5893                 :            : }
    5894                 :            : 
    5895                 :            : /* Expand a call to a unary builtin in EXP.
    5896                 :            :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5897                 :            :    function in-line.  If convenient, the result should be placed in TARGET.
    5898                 :            :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5899                 :            : 
    5900                 :            : static rtx
    5901                 :        240 : expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
    5902                 :            :                      rtx subtarget, optab op_optab)
    5903                 :            : {
    5904                 :        240 :   rtx op0;
    5905                 :            : 
    5906                 :        240 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5907                 :            :     return NULL_RTX;
    5908                 :            : 
    5909                 :            :   /* Compute the argument.  */
    5910                 :        480 :   op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
    5911                 :            :                      (subtarget
    5912                 :         28 :                       && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
    5913                 :         28 :                           == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
    5914                 :            :                      VOIDmode, EXPAND_NORMAL);
    5915                 :            :   /* Compute op, into TARGET if possible.
    5916                 :            :      Set TARGET to wherever the result comes back.  */
    5917                 :        240 :   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
    5918                 :            :                         op_optab, op0, target, op_optab != clrsb_optab);
    5919                 :        240 :   gcc_assert (target);
    5920                 :            : 
    5921                 :        240 :   return convert_to_mode (target_mode, target, 0);
    5922                 :            : }
    5923                 :            : 
    5924                 :            : /* Expand a call to __builtin_expect.  We just return our argument
    5925                 :            :    as the builtin_expect semantic should've been already executed by
    5926                 :            :    tree branch prediction pass. */
    5927                 :            : 
    5928                 :            : static rtx
    5929                 :        135 : expand_builtin_expect (tree exp, rtx target)
    5930                 :            : {
    5931                 :        135 :   tree arg;
    5932                 :            : 
    5933                 :        135 :   if (call_expr_nargs (exp) < 2)
    5934                 :          0 :     return const0_rtx;
    5935                 :        135 :   arg = CALL_EXPR_ARG (exp, 0);
    5936                 :            : 
    5937                 :        135 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5938                 :            :   /* When guessing was done, the hints should be already stripped away.  */
    5939                 :        135 :   gcc_assert (!flag_guess_branch_prob
    5940                 :            :               || optimize == 0 || seen_error ());
    5941                 :            :   return target;
    5942                 :            : }
    5943                 :            : 
    5944                 :            : /* Expand a call to __builtin_expect_with_probability.  We just return our
    5945                 :            :    argument as the builtin_expect semantic should've been already executed by
    5946                 :            :    tree branch prediction pass.  */
    5947                 :            : 
    5948                 :            : static rtx
    5949                 :          2 : expand_builtin_expect_with_probability (tree exp, rtx target)
    5950                 :            : {
    5951                 :          2 :   tree arg;
    5952                 :            : 
    5953                 :          2 :   if (call_expr_nargs (exp) < 3)
    5954                 :          0 :     return const0_rtx;
    5955                 :          2 :   arg = CALL_EXPR_ARG (exp, 0);
    5956                 :            : 
    5957                 :          2 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5958                 :            :   /* When guessing was done, the hints should be already stripped away.  */
    5959                 :          2 :   gcc_assert (!flag_guess_branch_prob
    5960                 :            :               || optimize == 0 || seen_error ());
    5961                 :            :   return target;
    5962                 :            : }
    5963                 :            : 
    5964                 :            : 
    5965                 :            : /* Expand a call to __builtin_assume_aligned.  We just return our first
    5966                 :            :    argument as the builtin_assume_aligned semantic should've been already
    5967                 :            :    executed by CCP.  */
    5968                 :            : 
    5969                 :            : static rtx
    5970                 :         85 : expand_builtin_assume_aligned (tree exp, rtx target)
    5971                 :            : {
    5972                 :         85 :   if (call_expr_nargs (exp) < 2)
    5973                 :          0 :     return const0_rtx;
    5974                 :         85 :   target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
    5975                 :            :                         EXPAND_NORMAL);
    5976                 :        170 :   gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
    5977                 :            :               && (call_expr_nargs (exp) < 3
    5978                 :            :                   || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
    5979                 :            :   return target;
    5980                 :            : }
    5981                 :            : 
    5982                 :            : void
    5983                 :      21707 : expand_builtin_trap (void)
    5984                 :            : {
    5985                 :      21707 :   if (targetm.have_trap ())
    5986                 :            :     {
    5987                 :      21707 :       rtx_insn *insn = emit_insn (targetm.gen_trap ());
    5988                 :            :       /* For trap insns when not accumulating outgoing args force
    5989                 :            :          REG_ARGS_SIZE note to prevent crossjumping of calls with
    5990                 :            :          different args sizes.  */
    5991                 :      21707 :       if (!ACCUMULATE_OUTGOING_ARGS)
    5992                 :      21705 :         add_args_size_note (insn, stack_pointer_delta);
    5993                 :            :     }
    5994                 :            :   else
    5995                 :            :     {
    5996                 :          0 :       tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
    5997                 :          0 :       tree call_expr = build_call_expr (fn, 0);
    5998                 :          0 :       expand_call (call_expr, NULL_RTX, false);
    5999                 :            :     }
    6000                 :            : 
    6001                 :      21707 :   emit_barrier ();
    6002                 :      21707 : }
    6003                 :            : 
    6004                 :            : /* Expand a call to __builtin_unreachable.  We do nothing except emit
    6005                 :            :    a barrier saying that control flow will not pass here.
    6006                 :            : 
    6007                 :            :    It is the responsibility of the program being compiled to ensure
    6008                 :            :    that control flow does never reach __builtin_unreachable.  */
    6009                 :            : static void
    6010                 :       2038 : expand_builtin_unreachable (void)
    6011                 :            : {
    6012                 :          0 :   emit_barrier ();
    6013                 :          0 : }
    6014                 :            : 
    6015                 :            : /* Expand EXP, a call to fabs, fabsf or fabsl.
    6016                 :            :    Return NULL_RTX if a normal call should be emitted rather than expanding
    6017                 :            :    the function inline.  If convenient, the result should be placed
    6018                 :            :    in TARGET.  SUBTARGET may be used as the target for computing
    6019                 :            :    the operand.  */
    6020                 :            : 
    6021                 :            : static rtx
    6022                 :          8 : expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
    6023                 :            : {
    6024                 :          8 :   machine_mode mode;
    6025                 :          8 :   tree arg;
    6026                 :          8 :   rtx op0;
    6027                 :            : 
    6028                 :          8 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6029                 :            :     return NULL_RTX;
    6030                 :            : 
    6031                 :          0 :   arg = CALL_EXPR_ARG (exp, 0);
    6032                 :          0 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    6033                 :          0 :   mode = TYPE_MODE (TREE_TYPE (arg));
    6034                 :          0 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6035                 :          0 :   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
    6036                 :            : }
    6037                 :            : 
    6038                 :            : /* Expand EXP, a call to copysign, copysignf, or copysignl.
    6039                 :            :    Return NULL is a normal call should be emitted rather than expanding the
    6040                 :            :    function inline.  If convenient, the result should be placed in TARGET.
    6041                 :            :    SUBTARGET may be used as the target for computing the operand.  */
    6042                 :            : 
    6043                 :            : static rtx
    6044                 :      11725 : expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
    6045                 :            : {
    6046                 :      11725 :   rtx op0, op1;
    6047                 :      11725 :   tree arg;
    6048                 :            : 
    6049                 :      11725 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    6050                 :            :     return NULL_RTX;
    6051                 :            : 
    6052                 :      11724 :   arg = CALL_EXPR_ARG (exp, 0);
    6053                 :      11724 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6054                 :            : 
    6055                 :      11724 :   arg = CALL_EXPR_ARG (exp, 1);
    6056                 :      11724 :   op1 = expand_normal (arg);
    6057                 :            : 
    6058                 :      11724 :   return expand_copysign (op0, op1, target);
    6059                 :            : }
    6060                 :            : 
    6061                 :            : /* Expand a call to __builtin___clear_cache.  */
    6062                 :            : 
    6063                 :            : static rtx
    6064                 :          1 : expand_builtin___clear_cache (tree exp)
    6065                 :            : {
    6066                 :          1 :   if (!targetm.code_for_clear_cache)
    6067                 :            :     {
    6068                 :            : #ifdef CLEAR_INSN_CACHE
    6069                 :            :       /* There is no "clear_cache" insn, and __clear_cache() in libgcc
    6070                 :            :          does something.  Just do the default expansion to a call to
    6071                 :            :          __clear_cache().  */
    6072                 :            :       return NULL_RTX;
    6073                 :            : #else
    6074                 :            :       /* There is no "clear_cache" insn, and __clear_cache() in libgcc
    6075                 :            :          does nothing.  There is no need to call it.  Do nothing.  */
    6076                 :          1 :       return const0_rtx;
    6077                 :            : #endif /* CLEAR_INSN_CACHE */
    6078                 :            :     }
    6079                 :            : 
    6080                 :            :   /* We have a "clear_cache" insn, and it will handle everything.  */
    6081                 :          0 :   tree begin, end;
    6082                 :          0 :   rtx begin_rtx, end_rtx;
    6083                 :            : 
    6084                 :            :   /* We must not expand to a library call.  If we did, any
    6085                 :            :      fallback library function in libgcc that might contain a call to
    6086                 :            :      __builtin___clear_cache() would recurse infinitely.  */
    6087                 :          0 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    6088                 :            :     {
    6089                 :          0 :       error ("both arguments to %<__builtin___clear_cache%> must be pointers");
    6090                 :          0 :       return const0_rtx;
    6091                 :            :     }
    6092                 :            : 
    6093                 :          0 :   if (targetm.have_clear_cache ())
    6094                 :            :     {
    6095                 :          0 :       class expand_operand ops[2];
    6096                 :            : 
    6097                 :          0 :       begin = CALL_EXPR_ARG (exp, 0);
    6098                 :          0 :       begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
    6099                 :            : 
    6100                 :          0 :       end = CALL_EXPR_ARG (exp, 1);
    6101                 :          0 :       end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
    6102                 :            : 
    6103                 :          0 :       create_address_operand (&ops[0], begin_rtx);
    6104                 :          0 :       create_address_operand (&ops[1], end_rtx);
    6105                 :          0 :       if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
    6106                 :          0 :         return const0_rtx;
    6107                 :            :     }
    6108                 :          0 :   return const0_rtx;
    6109                 :            : }
    6110                 :            : 
    6111                 :            : /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
    6112                 :            : 
    6113                 :            : static rtx
    6114                 :        613 : round_trampoline_addr (rtx tramp)
    6115                 :            : {
    6116                 :        613 :   rtx temp, addend, mask;
    6117                 :            : 
    6118                 :            :   /* If we don't need too much alignment, we'll have been guaranteed
    6119                 :            :      proper alignment by get_trampoline_type.  */
    6120                 :        613 :   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
    6121                 :            :     return tramp;
    6122                 :            : 
    6123                 :            :   /* Round address up to desired boundary.  */
    6124                 :          0 :   temp = gen_reg_rtx (Pmode);
    6125                 :          0 :   addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
    6126                 :          0 :   mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
    6127                 :            : 
    6128                 :          0 :   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
    6129                 :            :                                temp, 0, OPTAB_LIB_WIDEN);
    6130                 :          0 :   tramp = expand_simple_binop (Pmode, AND, temp, mask,
    6131                 :            :                                temp, 0, OPTAB_LIB_WIDEN);
    6132                 :            : 
    6133                 :          0 :   return tramp;
    6134                 :            : }
    6135                 :            : 
    6136                 :            : static rtx
    6137                 :        299 : expand_builtin_init_trampoline (tree exp, bool onstack)
    6138                 :            : {
    6139                 :        299 :   tree t_tramp, t_func, t_chain;
    6140                 :        299 :   rtx m_tramp, r_tramp, r_chain, tmp;
    6141                 :            : 
    6142                 :        299 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
    6143                 :            :                          POINTER_TYPE, VOID_TYPE))
    6144                 :            :     return NULL_RTX;
    6145                 :            : 
    6146                 :        299 :   t_tramp = CALL_EXPR_ARG (exp, 0);
    6147                 :        299 :   t_func = CALL_EXPR_ARG (exp, 1);
    6148                 :        299 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6149                 :            : 
    6150                 :        299 :   r_tramp = expand_normal (t_tramp);
    6151                 :        299 :   m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
    6152                 :        299 :   MEM_NOTRAP_P (m_tramp) = 1;
    6153                 :            : 
    6154                 :            :   /* If ONSTACK, the TRAMP argument should be the address of a field
    6155                 :            :      within the local function's FRAME decl.  Either way, let's see if
    6156                 :            :      we can fill in the MEM_ATTRs for this memory.  */
    6157                 :        299 :   if (TREE_CODE (t_tramp) == ADDR_EXPR)
    6158                 :        299 :     set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
    6159                 :            : 
    6160                 :            :   /* Creator of a heap trampoline is responsible for making sure the
    6161                 :            :      address is aligned to at least STACK_BOUNDARY.  Normally malloc
    6162                 :            :      will ensure this anyhow.  */
    6163                 :        299 :   tmp = round_trampoline_addr (r_tramp);
    6164                 :        299 :   if (tmp != r_tramp)
    6165                 :            :     {
    6166                 :          0 :       m_tramp = change_address (m_tramp, BLKmode, tmp);
    6167                 :          0 :       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
    6168                 :          0 :       set_mem_size (m_tramp, TRAMPOLINE_SIZE);
    6169                 :            :     }
    6170                 :            : 
    6171                 :            :   /* The FUNC argument should be the address of the nested function.
    6172                 :            :      Extract the actual function decl to pass to the hook.  */
    6173                 :        299 :   gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
    6174                 :        299 :   t_func = TREE_OPERAND (t_func, 0);
    6175                 :        299 :   gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
    6176                 :            : 
    6177                 :        299 :   r_chain = expand_normal (t_chain);
    6178                 :            : 
    6179                 :            :   /* Generate insns to initialize the trampoline.  */
    6180                 :        299 :   targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
    6181                 :            : 
    6182                 :        299 :   if (onstack)
    6183                 :            :     {
    6184                 :        299 :       trampolines_created = 1;
    6185                 :            : 
    6186                 :        299 :       if (targetm.calls.custom_function_descriptors != 0)
    6187                 :        299 :         warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
    6188                 :            :                     "trampoline generated for nested function %qD", t_func);
    6189                 :            :     }
    6190                 :            : 
    6191                 :        299 :   return const0_rtx;
    6192                 :            : }
    6193                 :            : 
    6194                 :            : static rtx
    6195                 :        314 : expand_builtin_adjust_trampoline (tree exp)
    6196                 :            : {
    6197                 :        314 :   rtx tramp;
    6198                 :            : 
    6199                 :        314 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6200                 :            :     return NULL_RTX;
    6201                 :            : 
    6202                 :        314 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6203                 :        314 :   tramp = round_trampoline_addr (tramp);
    6204                 :        314 :   if (targetm.calls.trampoline_adjust_address)
    6205                 :          0 :     tramp = targetm.calls.trampoline_adjust_address (tramp);
    6206                 :            : 
    6207                 :            :   return tramp;
    6208                 :            : }
    6209                 :            : 
    6210                 :            : /* Expand a call to the builtin descriptor initialization routine.
    6211                 :            :    A descriptor is made up of a couple of pointers to the static
    6212                 :            :    chain and the code entry in this order.  */
    6213                 :            : 
    6214                 :            : static rtx
    6215                 :          0 : expand_builtin_init_descriptor (tree exp)
    6216                 :            : {
    6217                 :          0 :   tree t_descr, t_func, t_chain;
    6218                 :          0 :   rtx m_descr, r_descr, r_func, r_chain;
    6219                 :            : 
    6220                 :          0 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
    6221                 :            :                          VOID_TYPE))
    6222                 :            :     return NULL_RTX;
    6223                 :            : 
    6224                 :          0 :   t_descr = CALL_EXPR_ARG (exp, 0);
    6225                 :          0 :   t_func = CALL_EXPR_ARG (exp, 1);
    6226                 :          0 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6227                 :            : 
    6228                 :          0 :   r_descr = expand_normal (t_descr);
    6229                 :          0 :   m_descr = gen_rtx_MEM (BLKmode, r_descr);
    6230                 :          0 :   MEM_NOTRAP_P (m_descr) = 1;
    6231                 :          0 :   set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
    6232                 :            : 
    6233                 :          0 :   r_func = expand_normal (t_func);
    6234                 :          0 :   r_chain = expand_normal (t_chain);
    6235                 :            : 
    6236                 :            :   /* Generate insns to initialize the descriptor.  */
    6237                 :          0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
    6238                 :          0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
    6239                 :            :                                      POINTER_SIZE / BITS_PER_UNIT), r_func);
    6240                 :            : 
    6241                 :          0 :   return const0_rtx;
    6242                 :            : }
    6243                 :            : 
    6244                 :            : /* Expand a call to the builtin descriptor adjustment routine.  */
    6245                 :            : 
    6246                 :            : static rtx
    6247                 :          0 : expand_builtin_adjust_descriptor (tree exp)
    6248                 :            : {
    6249                 :          0 :   rtx tramp;
    6250                 :            : 
    6251                 :          0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6252                 :            :     return NULL_RTX;
    6253                 :            : 
    6254                 :          0 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6255                 :            : 
    6256                 :            :   /* Unalign the descriptor to allow runtime identification.  */
    6257                 :          0 :   tramp = plus_constant (ptr_mode, tramp,
    6258                 :            :                          targetm.calls.custom_function_descriptors);
    6259                 :            : 
    6260                 :          0 :   return force_operand (tramp, NULL_RTX);
    6261                 :            : }
    6262                 :            : 
    6263                 :            : /* Expand the call EXP to the built-in signbit, signbitf or signbitl
    6264                 :            :    function.  The function first checks whether the back end provides
    6265                 :            :    an insn to implement signbit for the respective mode.  If not, it
    6266                 :            :    checks whether the floating point format of the value is such that
    6267                 :            :    the sign bit can be extracted.  If that is not the case, error out.
    6268                 :            :    EXP is the expression that is a call to the builtin function; if
    6269                 :            :    convenient, the result should be placed in TARGET.  */
    6270                 :            : static rtx
    6271                 :        774 : expand_builtin_signbit (tree exp, rtx target)
    6272                 :            : {
    6273                 :        774 :   const struct real_format *fmt;
    6274                 :        774 :   scalar_float_mode fmode;
    6275                 :        774 :   scalar_int_mode rmode, imode;
    6276                 :        774 :   tree arg;
    6277                 :        774 :   int word, bitpos;
    6278                 :        774 :   enum insn_code icode;
    6279                 :        774 :   rtx temp;
    6280                 :        774 :   location_t loc = EXPR_LOCATION (exp);
    6281                 :            : 
    6282                 :        774 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6283                 :            :     return NULL_RTX;
    6284                 :            : 
    6285                 :        774 :   arg = CALL_EXPR_ARG (exp, 0);
    6286                 :        774 :   fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    6287                 :        774 :   rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
    6288                 :        774 :   fmt = REAL_MODE_FORMAT (fmode);
    6289                 :            : 
    6290                 :        774 :   arg = builtin_save_expr (arg);
    6291                 :            : 
    6292                 :            :   /* Expand the argument yielding a RTX expression. */
    6293                 :        774 :   temp = expand_normal (arg);
    6294                 :            : 
    6295                 :            :   /* Check if the back end provides an insn that handles signbit for the
    6296                 :            :      argument's mode. */
    6297                 :        774 :   icode = optab_handler (signbit_optab, fmode);
    6298                 :        774 :   if (icode != CODE_FOR_nothing)
    6299                 :            :     {
    6300                 :          0 :       rtx_insn *last = get_last_insn ();
    6301                 :          0 :       target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    6302                 :          0 :       if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
    6303                 :            :         return target;
    6304                 :          0 :       delete_insns_since (last);
    6305                 :            :     }
    6306                 :            : 
    6307                 :            :   /* For floating point formats without a sign bit, implement signbit
    6308                 :            :      as "ARG < 0.0".  */
    6309                 :        774 :   bitpos = fmt->signbit_ro;
    6310                 :        774 :   if (bitpos < 0)
    6311                 :            :   {
    6312                 :            :     /* But we can't do this if the format supports signed zero.  */
    6313                 :          0 :     gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
    6314                 :            : 
    6315                 :          0 :     arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
    6316                 :          0 :                        build_real (TREE_TYPE (arg), dconst0));
    6317                 :          0 :     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    6318                 :            :   }
    6319                 :            : 
    6320                 :       1548 :   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
    6321                 :            :     {
    6322                 :        645 :       imode = int_mode_for_mode (fmode).require ();
    6323                 :        645 :       temp = gen_lowpart (imode, temp);
    6324                 :            :     }
    6325                 :            :   else
    6326                 :            :     {
    6327                 :        129 :       imode = word_mode;
    6328                 :            :       /* Handle targets with different FP word orders.  */
    6329                 :        129 :       if (FLOAT_WORDS_BIG_ENDIAN)
    6330                 :            :         word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
    6331                 :            :       else
    6332                 :        129 :         word = bitpos / BITS_PER_WORD;
    6333                 :        129 :       temp = operand_subword_force (temp, word, fmode);
    6334                 :        129 :       bitpos = bitpos % BITS_PER_WORD;
    6335                 :            :     }
    6336                 :            : 
    6337                 :            :   /* Force the intermediate word_mode (or narrower) result into a
    6338                 :            :      register.  This avoids attempting to create paradoxical SUBREGs
    6339                 :            :      of floating point modes below.  */
    6340                 :        774 :   temp = force_reg (imode, temp);
    6341                 :            : 
    6342                 :            :   /* If the bitpos is within the "result mode" lowpart, the operation
    6343                 :            :      can be implement with a single bitwise AND.  Otherwise, we need
    6344                 :            :      a right shift and an AND.  */
    6345                 :            : 
    6346                 :       1548 :   if (bitpos < GET_MODE_BITSIZE (rmode))
    6347                 :            :     {
    6348                 :        516 :       wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
    6349                 :            : 
    6350                 :       1548 :       if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
    6351                 :          0 :         temp = gen_lowpart (rmode, temp);
    6352                 :        516 :       temp = expand_binop (rmode, and_optab, temp,
    6353                 :            :                            immed_wide_int_const (mask, rmode),
    6354                 :            :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6355                 :            :     }
    6356                 :            :   else
    6357                 :            :     {
    6358                 :            :       /* Perform a logical right shift to place the signbit in the least
    6359                 :            :          significant bit, then truncate the result to the desired mode
    6360                 :            :          and mask just this bit.  */
    6361                 :        258 :       temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
    6362                 :        258 :       temp = gen_lowpart (rmode, temp);
    6363                 :        258 :       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
    6364                 :            :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6365                 :            :     }
    6366                 :            : 
    6367                 :            :   return temp;
    6368                 :            : }
    6369                 :            : 
    6370                 :            : /* Expand fork or exec calls.  TARGET is the desired target of the
    6371                 :            :    call.  EXP is the call. FN is the
    6372                 :            :    identificator of the actual function.  IGNORE is nonzero if the
    6373                 :            :    value is to be ignored.  */
    6374                 :            : 
    6375                 :            : static rtx
    6376                 :         81 : expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
    6377                 :            : {
    6378                 :         81 :   tree id, decl;
    6379                 :         81 :   tree call;
    6380                 :            : 
    6381                 :         81 :   if (DECL_FUNCTION_CODE (fn) != BUILT_IN_FORK)
    6382                 :            :     {
    6383                 :            :       /* Detect unterminated path.  */
    6384                 :         24 :       if (!check_nul_terminated_array (exp, CALL_EXPR_ARG (exp, 0)))
    6385                 :            :         return NULL_RTX;
    6386                 :            : 
    6387                 :            :       /* Also detect unterminated first argument.  */
    6388                 :         17 :       switch (DECL_FUNCTION_CODE (fn))
    6389                 :            :         {
    6390                 :          1 :         case BUILT_IN_EXECL:
    6391                 :          1 :         case BUILT_IN_EXECLE:
    6392                 :          1 :         case BUILT_IN_EXECLP:
    6393                 :          1 :           if (!check_nul_terminated_array (exp, CALL_EXPR_ARG (exp, 0)))
    6394                 :            :             return NULL_RTX;
    6395                 :            :         default:
    6396                 :            :           break;
    6397                 :            :         }
    6398                 :            :     }
    6399                 :            : 
    6400                 :            : 
    6401                 :            :   /* If we are not profiling, just call the function.  */
    6402                 :         74 :   if (!profile_arc_flag)
    6403                 :            :     return NULL_RTX;
    6404                 :            : 
    6405                 :            :   /* Otherwise call the wrapper.  This should be equivalent for the rest of
    6406                 :            :      compiler, so the code does not diverge, and the wrapper may run the
    6407                 :            :      code necessary for keeping the profiling sane.  */
    6408                 :            : 
    6409                 :          4 :   switch (DECL_FUNCTION_CODE (fn))
    6410                 :            :     {
    6411                 :          4 :     case BUILT_IN_FORK:
    6412                 :          4 :       id = get_identifier ("__gcov_fork");
    6413                 :          4 :       break;
    6414                 :            : 
    6415                 :          0 :     case BUILT_IN_EXECL:
    6416                 :          0 :       id = get_identifier ("__gcov_execl");
    6417                 :          0 :       break;
    6418                 :            : 
    6419                 :          0 :     case BUILT_IN_EXECV:
    6420                 :          0 :       id = get_identifier ("__gcov_execv");
    6421                 :          0 :       break;
    6422                 :            : 
    6423                 :          0 :     case BUILT_IN_EXECLP:
    6424                 :          0 :       id = get_identifier ("__gcov_execlp");
    6425                 :          0 :       break;
    6426                 :            : 
    6427                 :          0 :     case BUILT_IN_EXECLE:
    6428                 :          0 :       id = get_identifier ("__gcov_execle");
    6429                 :          0 :       break;
    6430                 :            : 
    6431                 :          0 :     case BUILT_IN_EXECVP:
    6432                 :          0 :       id = get_identifier ("__gcov_execvp");
    6433                 :          0 :       break;
    6434                 :            : 
    6435                 :          0 :     case BUILT_IN_EXECVE:
    6436                 :          0 :       id = get_identifier ("__gcov_execve");
    6437                 :          0 :       break;
    6438                 :            : 
    6439                 :          0 :     default:
    6440                 :          0 :       gcc_unreachable ();
    6441                 :            :     }
    6442                 :            : 
    6443                 :          8 :   decl = build_decl (DECL_SOURCE_LOCATION (fn),
    6444                 :          4 :                      FUNCTION_DECL, id, TREE_TYPE (fn));
    6445                 :          4 :   DECL_EXTERNAL (decl) = 1;
    6446                 :          4 :   TREE_PUBLIC (decl) = 1;
    6447                 :          4 :   DECL_ARTIFICIAL (decl) = 1;
    6448                 :          4 :   TREE_NOTHROW (decl) = 1;
    6449                 :          4 :   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    6450                 :          4 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
    6451                 :          4 :   call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
    6452                 :          4 :   return expand_call (call, target, ignore);
    6453                 :            :  }
    6454                 :            : 
    6455                 :            : 
    6456                 :            : 
    6457                 :            : /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
    6458                 :            :    the pointer in these functions is void*, the tree optimizers may remove
    6459                 :            :    casts.  The mode computed in expand_builtin isn't reliable either, due
    6460                 :            :    to __sync_bool_compare_and_swap.
    6461                 :            : 
    6462                 :            :    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
    6463                 :            :    group of builtins.  This gives us log2 of the mode size.  */
    6464                 :            : 
    6465                 :            : static inline machine_mode
    6466                 :     108519 : get_builtin_sync_mode (int fcode_diff)
    6467                 :            : {
    6468                 :            :   /* The size is not negotiable, so ask not to get BLKmode in return
    6469                 :            :      if the target indicates that a smaller size would be better.  */
    6470                 :     217038 :   return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
    6471                 :            : }
    6472                 :            : 
    6473                 :            : /* Expand the memory expression LOC and return the appropriate memory operand
    6474                 :            :    for the builtin_sync operations.  */
    6475                 :            : 
    6476                 :            : static rtx
    6477                 :     115769 : get_builtin_sync_mem (tree loc, machine_mode mode)
    6478                 :            : {
    6479                 :     115769 :   rtx addr, mem;
    6480                 :     115769 :   int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
    6481                 :            :                                     ? TREE_TYPE (TREE_TYPE (loc))
    6482                 :            :                                     : TREE_TYPE (loc));
    6483                 :     115769 :   scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
    6484                 :            : 
    6485                 :     115769 :   addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
    6486                 :     115769 :   addr = convert_memory_address (addr_mode, addr);
    6487                 :            : 
    6488                 :            :   /* Note that we explicitly do not want any alias information for this
    6489                 :            :      memory, so that we kill all other live memories.  Otherwise we don't
    6490                 :            :      satisfy the full barrier semantics of the intrinsic.  */
    6491                 :     115769 :   mem = gen_rtx_MEM (mode, addr);
    6492                 :            : 
    6493                 :     115769 :   set_mem_addr_space (mem, addr_space);
    6494                 :            : 
    6495                 :     115769 :   mem = validize_mem (mem);
    6496                 :            : 
    6497                 :            :   /* The alignment needs to be at least according to that of the mode.  */
    6498                 :     115769 :   set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
    6499                 :            :                            get_pointer_alignment (loc)));
    6500                 :     115769 :   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
    6501                 :     115769 :   MEM_VOLATILE_P (mem) = 1;
    6502                 :            : 
    6503                 :     115769 :   return mem;
    6504                 :            : }
    6505                 :            : 
    6506                 :            : /* Make sure an argument is in the right mode.
    6507                 :            :    EXP is the tree argument. 
    6508                 :            :    MODE is the mode it should be in.  */
    6509                 :            : 
    6510                 :            : static rtx
    6511                 :      73085 : expand_expr_force_mode (tree exp, machine_mode mode)
    6512                 :            : {
    6513                 :      73085 :   rtx val;
    6514                 :      73085 :   machine_mode old_mode;
    6515                 :            : 
    6516                 :      73085 :   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
    6517                 :            :   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
    6518                 :            :      of CONST_INTs, where we know the old_mode only from the call argument.  */
    6519                 :            : 
    6520                 :      73085 :   old_mode = GET_MODE (val);
    6521                 :      73085 :   if (old_mode == VOIDmode)
    6522                 :      38387 :     old_mode = TYPE_MODE (TREE_TYPE (exp));
    6523                 :      73085 :   val = convert_modes (mode, old_mode, val, 1);
    6524                 :      73085 :   return val;
    6525                 :            : }
    6526                 :            : 
    6527                 :            : 
    6528                 :            : /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
    6529                 :            :    EXP is the CALL_EXPR.  CODE is the rtx code
    6530                 :            :    that corresponds to the arithmetic or logical operation from the name;
    6531                 :            :    an exception here is that NOT actually means NAND.  TARGET is an optional
    6532                 :            :    place for us to store the results; AFTER is true if this is the
    6533                 :            :    fetch_and_xxx form.  */
    6534                 :            : 
    6535                 :            : static rtx
    6536                 :       3508 : expand_builtin_sync_operation (machine_mode mode, tree exp,
    6537                 :            :                                enum rtx_code code, bool after,
    6538                 :            :                                rtx target)
    6539                 :            : {
    6540                 :       3508 :   rtx val, mem;
    6541                 :       3508 :   location_t loc = EXPR_LOCATION (exp);
    6542                 :            : 
    6543                 :       3508 :   if (code == NOT && warn_sync_nand)
    6544                 :            :     {
    6545                 :        519 :       tree fndecl = get_callee_fndecl (exp);
    6546                 :        519 :       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    6547                 :            : 
    6548                 :        519 :       static bool warned_f_a_n, warned_n_a_f;
    6549                 :            : 
    6550                 :        519 :       switch (fcode)
    6551                 :            :         {
    6552                 :        435 :         case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    6553                 :        435 :         case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    6554                 :        435 :         case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    6555                 :        435 :         case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    6556                 :        435 :         case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    6557                 :        435 :           if (warned_f_a_n)
    6558                 :            :             break;
    6559                 :            : 
    6560                 :         31 :           fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
    6561                 :         31 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6562                 :         31 :           warned_f_a_n = true;
    6563                 :         31 :           break;
    6564                 :            : 
    6565                 :         84 :         case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    6566                 :         84 :         case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    6567                 :         84 :         case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    6568                 :         84 :         case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    6569                 :         84 :         case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    6570                 :         84 :           if (warned_n_a_f)
    6571                 :            :             break;
    6572                 :            : 
    6573                 :         17 :          fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
    6574                 :         17 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6575                 :         17 :           warned_n_a_f = true;
    6576                 :         17 :           break;
    6577                 :            : 
    6578                 :          0 :         default:
    6579                 :          0 :           gcc_unreachable ();
    6580                 :            :         }
    6581                 :            :     }
    6582                 :            : 
    6583                 :            :   /* Expand the operands.  */
    6584                 :       3508 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6585                 :       3508 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6586                 :            : 
    6587                 :       3508 :   return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
    6588                 :       3508 :                                  after);
    6589                 :            : }
    6590                 :            : 
    6591                 :            : /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
    6592                 :            :    intrinsics. EXP is the CALL_EXPR.  IS_BOOL is
    6593                 :            :    true if this is the boolean form.  TARGET is a place for us to store the
    6594                 :            :    results; this is NOT optional if IS_BOOL is true.  */
    6595                 :            : 
    6596                 :            : static rtx
    6597                 :       2330 : expand_builtin_compare_and_swap (machine_mode mode, tree exp,
    6598                 :            :                                  bool is_bool, rtx target)
    6599                 :            : {
    6600                 :       2330 :   rtx old_val, new_val, mem;
    6601                 :       2330 :   rtx *pbool, *poval;
    6602                 :            : 
    6603                 :            :   /* Expand the operands.  */
    6604                 :       2330 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6605                 :       2330 :   old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6606                 :       2330 :   new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6607                 :            : 
    6608                 :       2330 :   pbool = poval = NULL;
    6609                 :       2330 :   if (target != const0_rtx)
    6610                 :            :     {
    6611                 :       2304 :       if (is_bool)
    6612                 :            :         pbool = &target;
    6613                 :            :       else
    6614                 :       2130 :         poval = &target;
    6615                 :            :     }
    6616                 :       2330 :   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
    6617                 :            :                                        false, MEMMODEL_SYNC_SEQ_CST,
    6618                 :            :                                        MEMMODEL_SYNC_SEQ_CST))
    6619                 :            :     return NULL_RTX;
    6620                 :            : 
    6621                 :       2329 :   return target;
    6622                 :            : }
    6623                 :            : 
    6624                 :            : /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
    6625                 :            :    general form is actually an atomic exchange, and some targets only
    6626                 :            :    support a reduced form with the second argument being a constant 1.
    6627                 :            :    EXP is the CALL_EXPR; TARGET is an optional place for us to store
    6628                 :            :    the results.  */
    6629                 :            : 
    6630                 :            : static rtx
    6631                 :        805 : expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
    6632                 :            :                                        rtx target)
    6633                 :            : {
    6634                 :        805 :   rtx val, mem;
    6635                 :            : 
    6636                 :            :   /* Expand the operands.  */
    6637                 :        805 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6638                 :        805 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6639                 :            : 
    6640                 :        805 :   return expand_sync_lock_test_and_set (target, mem, val);
    6641                 :            : }
    6642                 :            : 
    6643                 :            : /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
    6644                 :            : 
    6645                 :            : static void
    6646                 :        108 : expand_builtin_sync_lock_release (machine_mode mode, tree exp)
    6647                 :            : {
    6648                 :        108 :   rtx mem;
    6649                 :            : 
    6650                 :            :   /* Expand the operands.  */
    6651                 :        108 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6652                 :            : 
    6653                 :        108 :   expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
    6654                 :        108 : }
    6655                 :            : 
    6656                 :            : /* Given an integer representing an ``enum memmodel'', verify its
    6657                 :            :    correctness and return the memory model enum.  */
    6658                 :            : 
    6659                 :            : static enum memmodel
    6660                 :     125603 : get_memmodel (tree exp)
    6661                 :            : {
    6662                 :     125603 :   rtx op;
    6663                 :     125603 :   unsigned HOST_WIDE_INT val;
    6664                 :     125603 :   location_t loc
    6665                 :     125603 :     = expansion_point_location_if_in_system_header (input_location);
    6666                 :            : 
    6667                 :            :   /* If the parameter is not a constant, it's a run time value so we'll just
    6668                 :            :      convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking.  */
    6669                 :     125603 :   if (TREE_CODE (exp) != INTEGER_CST)
    6670                 :            :     return MEMMODEL_SEQ_CST;
    6671                 :            : 
    6672                 :     125490 :   op = expand_normal (exp);
    6673                 :            : 
    6674                 :     125490 :   val = INTVAL (op);
    6675                 :     125490 :   if (targetm.memmodel_check)
    6676                 :     125490 :     val = targetm.memmodel_check (val);
    6677                 :          0 :   else if (val & ~MEMMODEL_MASK)
    6678                 :            :     {
    6679                 :          0 :       warning_at (loc, OPT_Winvalid_memory_model,
    6680                 :            :                   "unknown architecture specifier in memory model to builtin");
    6681                 :          0 :       return MEMMODEL_SEQ_CST;
    6682                 :            :     }
    6683                 :            : 
    6684                 :            :   /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
    6685                 :     125490 :   if (memmodel_base (val) >= MEMMODEL_LAST)
    6686                 :            :     {
    6687                 :          1 :       warning_at (loc, OPT_Winvalid_memory_model,
    6688                 :            :                   "invalid memory model argument to builtin");
    6689                 :          1 :       return MEMMODEL_SEQ_CST;
    6690                 :            :     }
    6691                 :            : 
    6692                 :            :   /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
    6693                 :            :      be conservative and promote consume to acquire.  */
    6694                 :     125489 :   if (val == MEMMODEL_CONSUME)
    6695                 :        638 :     val = MEMMODEL_ACQUIRE;
    6696                 :            : 
    6697                 :     125489 :   return (enum memmodel) val;
    6698                 :            : }
    6699                 :            : 
    6700                 :            : /* Expand the __atomic_exchange intrinsic:
    6701                 :            :         TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
    6702                 :            :    EXP is the CALL_EXPR.
    6703                 :            :    TARGET is an optional place for us to store the results.  */
    6704                 :            : 
    6705                 :            : static rtx
    6706                 :       1625 : expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
    6707                 :            : {
    6708                 :       1625 :   rtx val, mem;
    6709                 :       1625 :   enum memmodel model;
    6710                 :            : 
    6711                 :       1625 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6712                 :            : 
    6713                 :       1625 :   if (!flag_inline_atomics)
    6714                 :            :     return NULL_RTX;
    6715                 :            : 
    6716                 :            :   /* Expand the operands.  */
    6717                 :       1574 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6718                 :       1574 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6719                 :            : 
    6720                 :       1574 :   return expand_atomic_exchange (target, mem, val, model);
    6721                 :            : }
    6722                 :            : 
    6723                 :            : /* Expand the __atomic_compare_exchange intrinsic:
    6724                 :            :         bool __atomic_compare_exchange (TYPE *object, TYPE *expect, 
    6725                 :            :                                         TYPE desired, BOOL weak, 
    6726                 :            :                                         enum memmodel success,
    6727                 :            :                                         enum memmodel failure)
    6728                 :            :    EXP is the CALL_EXPR.
    6729                 :            :    TARGET is an optional place for us to store the results.  */
    6730                 :            : 
    6731                 :            : static rtx
    6732                 :       8756 : expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp, 
    6733                 :            :                                         rtx target)
    6734                 :            : {
    6735                 :       8756 :   rtx expect, desired, mem, oldval;
    6736                 :       8756 :   rtx_code_label *label;
    6737                 :       8756 :   enum memmodel success, failure;
    6738                 :       8756 :   tree weak;
    6739                 :       8756 :   bool is_weak;
    6740                 :       8756 :   location_t loc
    6741                 :       8756 :     = expansion_point_location_if_in_system_header (input_location);
    6742                 :            : 
    6743                 :       8756 :   success = get_memmodel (CALL_EXPR_ARG (exp, 4));
    6744                 :       8756 :   failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
    6745                 :            : 
    6746                 :       8756 :   if (failure > success)
    6747                 :            :     {
    6748                 :          8 :       warning_at (loc, OPT_Winvalid_memory_model,
    6749                 :            :                   "failure memory model cannot be stronger than success "
    6750                 :            :                   "memory model for %<__atomic_compare_exchange%>");
    6751                 :          8 :       success = MEMMODEL_SEQ_CST;
    6752                 :            :     }
    6753                 :            :  
    6754                 :       8756 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6755                 :            :     {
    6756                 :          6 :       warning_at (loc, OPT_Winvalid_memory_model,
    6757                 :            :                   "invalid failure memory model for "
    6758                 :            :                   "%<__atomic_compare_exchange%>");
    6759                 :          6 :       failure = MEMMODEL_SEQ_CST;
    6760                 :          6 :       success = MEMMODEL_SEQ_CST;
    6761                 :            :     }
    6762                 :            : 
    6763                 :            :  
    6764                 :       8756 :   if (!flag_inline_atomics)
    6765                 :            :     return NULL_RTX;
    6766                 :            : 
    6767                 :            :   /* Expand the operands.  */
    6768                 :       8705 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6769                 :            : 
    6770                 :       8705 :   expect = expand_normal (CALL_EXPR_ARG (exp, 1));
    6771                 :      17410 :   expect = convert_memory_address (Pmode, expect);
    6772                 :       8705 :   expect = gen_rtx_MEM (mode, expect);
    6773                 :       8705 :   desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6774                 :            : 
    6775                 :       8705 :   weak = CALL_EXPR_ARG (exp, 3);
    6776                 :       8705 :   is_weak = false;
    6777                 :       8705 :   if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
    6778                 :        197 :     is_weak = true;
    6779                 :            : 
    6780                 :       8705 :   if (target == const0_rtx)
    6781                 :         70 :     target = NULL;
    6782                 :            : 
    6783                 :            :   /* Lest the rtl backend create a race condition with an imporoper store
    6784                 :            :      to memory, always create a new pseudo for OLDVAL.  */
    6785                 :       8705 :   oldval = NULL;
    6786                 :            : 
    6787                 :       8705 :   if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
    6788                 :            :                                        is_weak, success, failure))
    6789                 :            :     return NULL_RTX;
    6790                 :            : 
    6791                 :            :   /* Conditionally store back to EXPECT, lest we create a race condition
    6792                 :            :      with an improper store to memory.  */
    6793                 :            :   /* ??? With a rearrangement of atomics at the gimple level, we can handle
    6794                 :            :      the normal case where EXPECT is totally private, i.e. a register.  At
    6795                 :            :      which point the store can be unconditional.  */
    6796                 :       7025 :   label = gen_label_rtx ();
    6797                 :       7025 :   emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
    6798                 :       7025 :                            GET_MODE (target), 1, label);
    6799                 :       7025 :   emit_move_insn (expect, oldval);
    6800                 :       7025 :   emit_label (label);
    6801                 :            : 
    6802                 :       7025 :   return target;
    6803                 :            : }
    6804                 :            : 
    6805                 :            : /* Helper function for expand_ifn_atomic_compare_exchange - expand
    6806                 :            :    internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
    6807                 :            :    call.  The weak parameter must be dropped to match the expected parameter
    6808                 :            :    list and the expected argument changed from value to pointer to memory
    6809                 :            :    slot.  */
    6810                 :            : 
    6811                 :            : static void
    6812                 :          0 : expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
    6813                 :            : {
    6814                 :          0 :   unsigned int z;
    6815                 :          0 :   vec<tree, va_gc> *vec;
    6816                 :            : 
    6817                 :          0 :   vec_alloc (vec, 5);
    6818                 :          0 :   vec->quick_push (gimple_call_arg (call, 0));
    6819                 :          0 :   tree expected = gimple_call_arg (call, 1);
    6820                 :          0 :   rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
    6821                 :          0 :                                       TREE_TYPE (expected));
    6822                 :          0 :   rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
    6823                 :          0 :   if (expd != x)
    6824                 :          0 :     emit_move_insn (x, expd);
    6825                 :          0 :   tree v = make_tree (TREE_TYPE (expected), x);
    6826                 :          0 :   vec->quick_push (build1 (ADDR_EXPR,
    6827                 :          0 :                            build_pointer_type (TREE_TYPE (expected)), v));
    6828                 :          0 :   vec->quick_push (gimple_call_arg (call, 2));
    6829                 :            :   /* Skip the boolean weak parameter.  */
    6830                 :          0 :   for (z = 4; z < 6; z++)
    6831                 :          0 :     vec->quick_push (gimple_call_arg (call, z));
    6832                 :            :   /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}.  */
    6833                 :          0 :   unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
    6834                 :          0 :   gcc_assert (bytes_log2 < 5);
    6835                 :          0 :   built_in_function fncode
    6836                 :            :     = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
    6837                 :            :                            + bytes_log2);
    6838                 :          0 :   tree fndecl = builtin_decl_explicit (fncode);
    6839                 :          0 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
    6840                 :            :                     fndecl);
    6841                 :          0 :   tree exp = build_call_vec (boolean_type_node, fn, vec);
    6842                 :          0 :   tree lhs = gimple_call_lhs (call);
    6843                 :          0 :   rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
    6844                 :          0 :   if (lhs)
    6845                 :            :     {
    6846                 :          0 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6847                 :          0 :       if (GET_MODE (boolret) != mode)
    6848                 :          0 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6849                 :          0 :       x = force_reg (mode, x);
    6850                 :          0 :       write_complex_part (target, boolret, true);
    6851                 :          0 :       write_complex_part (target, x, false);
    6852                 :            :     }
    6853                 :          0 : }
    6854                 :            : 
    6855                 :            : /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function.  */
    6856                 :            : 
    6857                 :            : void
    6858                 :       7019 : expand_ifn_atomic_compare_exchange (gcall *call)
    6859                 :            : {
    6860                 :       7019 :   int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
    6861                 :       7019 :   gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
    6862                 :      14038 :   machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
    6863                 :       7019 :   rtx expect, desired, mem, oldval, boolret;
    6864                 :       7019 :   enum memmodel success, failure;
    6865                 :       7019 :   tree lhs;
    6866                 :       7019 :   bool is_weak;
    6867                 :       7019 :   location_t loc
    6868                 :       7019 :     = expansion_point_location_if_in_system_header (gimple_location (call));
    6869                 :            : 
    6870                 :       7019 :   success = get_memmodel (gimple_call_arg (call, 4));
    6871                 :       7019 :   failure = get_memmodel (gimple_call_arg (call, 5));
    6872                 :            : 
    6873                 :       7019 :   if (failure > success)
    6874                 :            :     {
    6875                 :          0 :       warning_at (loc, OPT_Winvalid_memory_model,
    6876                 :            :                   "failure memory model cannot be stronger than success "
    6877                 :            :                   "memory model for %<__atomic_compare_exchange%>");
    6878                 :          0 :       success = MEMMODEL_SEQ_CST;
    6879                 :            :     }
    6880                 :            : 
    6881                 :       7019 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6882                 :            :     {
    6883                 :          0 :       warning_at (loc, OPT_Winvalid_memory_model,
    6884                 :            :                   "invalid failure memory model for "
    6885                 :            :                   "%<__atomic_compare_exchange%>");
    6886                 :          0 :       failure = MEMMODEL_SEQ_CST;
    6887                 :          0 :       success = MEMMODEL_SEQ_CST;
    6888                 :            :     }
    6889                 :            : 
    6890                 :       7019 :   if (!flag_inline_atomics)
    6891                 :            :     {
    6892                 :          0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6893                 :          0 :       return;
    6894                 :            :     }
    6895                 :            : 
    6896                 :            :   /* Expand the operands.  */
    6897                 :       7019 :   mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
    6898                 :            : 
    6899                 :       7019 :   expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
    6900                 :       7019 :   desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
    6901                 :            : 
    6902                 :       7019 :   is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
    6903                 :            : 
    6904                 :       7019 :   boolret = NULL;
    6905                 :       7019 :   oldval = NULL;
    6906                 :            : 
    6907                 :       7019 :   if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
    6908                 :            :                                        is_weak, success, failure))
    6909                 :            :     {
    6910                 :          0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6911                 :          0 :       return;
    6912                 :            :     }
    6913                 :            : 
    6914                 :       7019 :   lhs = gimple_call_lhs (call);
    6915                 :       7019 :   if (lhs)
    6916                 :            :     {
    6917                 :       6871 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6918                 :       6871 :       if (GET_MODE (boolret) != mode)
    6919                 :       5639 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6920                 :       6871 :       write_complex_part (target, boolret, true);
    6921                 :       6871 :       write_complex_part (target, oldval, false);
    6922                 :            :     }
    6923                 :            : }
    6924                 :            : 
    6925                 :            : /* Expand the __atomic_load intrinsic:
    6926                 :            :         TYPE __atomic_load (TYPE *object, enum memmodel)
    6927                 :            :    EXP is the CALL_EXPR.
    6928                 :            :    TARGET is an optional place for us to store the results.  */
    6929                 :            : 
    6930                 :            : static rtx
    6931                 :      51676 : expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
    6932                 :            : {
    6933                 :      51676 :   rtx mem;
    6934                 :      51676 :   enum memmodel model;
    6935                 :            : 
    6936                 :      51676 :   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    6937                 :      51676 :   if (is_mm_release (model) || is_mm_acq_rel (model))
    6938                 :            :     {
    6939                 :          4 :       location_t loc
    6940                 :          4 :         = expansion_point_location_if_in_system_header (input_location);
    6941                 :          4 :       warning_at (loc, OPT_Winvalid_memory_model,
    6942                 :            :                   "invalid memory model for %<__atomic_load%>");
    6943                 :          4 :       model = MEMMODEL_SEQ_CST;
    6944                 :            :     }
    6945                 :            : 
    6946                 :      51676 :   if (!flag_inline_atomics)
    6947                 :            :     return NULL_RTX;
    6948                 :            : 
    6949                 :            :   /* Expand the operand.  */
    6950                 :      51635 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6951                 :            : 
    6952                 :      51635 :   return expand_atomic_load (target, mem, model);
    6953                 :            : }
    6954                 :            : 
    6955                 :            : 
    6956                 :            : /* Expand the __atomic_store intrinsic:
    6957                 :            :         void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
    6958                 :            :    EXP is the CALL_EXPR.
    6959                 :            :    TARGET is an optional place for us to store the results.  */
    6960                 :            : 
    6961                 :            : static rtx
    6962                 :      14060 : expand_builtin_atomic_store (machine_mode mode, tree exp)
    6963                 :            : {
    6964                 :      14060 :   rtx mem, val;
    6965                 :      14060 :   enum memmodel model;
    6966                 :            : 
    6967                 :      14060 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6968                 :      14060 :   if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
    6969                 :        403 :         || is_mm_release (model)))
    6970                 :            :     {
    6971                 :          6 :       location_t loc
    6972                 :          6 :         = expansion_point_location_if_in_system_header (input_location);
    6973                 :          6 :       warning_at (loc, OPT_Winvalid_memory_model,
    6974                 :            :                   "invalid memory model for %<__atomic_store%>");
    6975                 :          6 :       model = MEMMODEL_SEQ_CST;
    6976                 :            :     }
    6977                 :            : 
    6978                 :      14060 :   if (!flag_inline_atomics)
    6979                 :            :     return NULL_RTX;
    6980                 :            : 
    6981                 :            :   /* Expand the operands.  */
    6982                 :      14029 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6983                 :      14029 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6984                 :            : 
    6985                 :      14029 :   return expand_atomic_store (mem, val, model, false);
    6986                 :            : }
    6987                 :            : 
    6988                 :            : /* Expand the __atomic_fetch_XXX intrinsic:
    6989                 :            :         TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
    6990                 :            :    EXP is the CALL_EXPR.
    6991                 :            :    TARGET is an optional place for us to store the results.
    6992                 :            :    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
    6993                 :            :    FETCH_AFTER is true if returning the result of the operation.
    6994                 :            :    FETCH_AFTER is false if returning the value before the operation.
    6995                 :            :    IGNORE is true if the result is not used.
    6996                 :            :    EXT_CALL is the correct builtin for an external call if this cannot be
    6997                 :            :    resolved to an instruction sequence.  */
    6998                 :            : 
    6999                 :            : static rtx
    7000                 :      25615 : expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
    7001                 :            :                                 enum rtx_code code, bool fetch_after,
    7002                 :            :                                 bool ignore, enum built_in_function ext_call)
    7003                 :            : {
    7004                 :      25615 :   rtx val, mem, ret;
    7005                 :      25615 :   enum memmodel model;
    7006                 :      25615 :   tree fndecl;
    7007                 :      25615 :   tree addr;
    7008                 :            : 
    7009                 :      25615 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    7010                 :            : 
    7011                 :            :   /* Expand the operands.  */
    7012                 :      25615 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7013                 :      25615 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    7014                 :            : 
    7015                 :            :   /* Only try generating instructions if inlining is turned on.  */
    7016                 :      25615 :   if (flag_inline_atomics)
    7017                 :            :     {
    7018                 :      25072 :       ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
    7019                 :      25072 :       if (ret)
    7020                 :            :         return ret;
    7021                 :            :     }
    7022                 :            : 
    7023                 :            :   /* Return if a different routine isn't needed for the library call.  */
    7024                 :        571 :   if (ext_call == BUILT_IN_NONE)
    7025                 :            :     return NULL_RTX;
    7026                 :            : 
    7027                 :            :   /* Change the call to the specified function.  */
    7028                 :        286 :   fndecl = get_callee_fndecl (exp);
    7029                 :        286 :   addr = CALL_EXPR_FN (exp);
    7030                 :        286 :   STRIP_NOPS (addr);
    7031                 :            : 
    7032                 :        286 :   gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
    7033                 :        286 :   TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
    7034                 :            : 
    7035                 :            :   /* If we will emit code after the call, the call cannot be a tail call.
    7036                 :            :      If it is emitted as a tail call, a barrier is emitted after it, and
    7037                 :            :      then all trailing code is removed.  */
    7038                 :        286 :   if (!ignore)
    7039                 :        182 :     CALL_EXPR_TAILCALL (exp) = 0;
    7040                 :            : 
    7041                 :            :   /* Expand the call here so we can emit trailing code.  */
    7042                 :        286 :   ret = expand_call (exp, target, ignore);
    7043                 :            : 
    7044                 :            :   /* Replace the original function just in case it matters.  */
    7045                 :        286 :   TREE_OPERAND (addr, 0) = fndecl;
    7046                 :            : 
    7047                 :            :   /* Then issue the arithmetic correction to return the right result.  */
    7048                 :        286 :   if (!ignore)
    7049                 :            :     {
    7050                 :        182 :       if (code == NOT)
    7051                 :            :         {
    7052                 :         31 :           ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
    7053                 :            :                                      OPTAB_LIB_WIDEN);
    7054                 :         31 :           ret = expand_simple_unop (mode, NOT, ret, target, true);
    7055                 :            :         }
    7056                 :            :       else
    7057                 :        151 :         ret = expand_simple_binop (mode, code, ret, val, target, true,
    7058                 :            :                                    OPTAB_LIB_WIDEN);
    7059                 :            :     }
    7060                 :            :   return ret;
    7061                 :            : }
    7062                 :            : 
    7063                 :            : /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function.  */
    7064                 :            : 
    7065                 :            : void
    7066                 :        151 : expand_ifn_atomic_bit_test_and (gcall *call)
    7067                 :            : {
    7068                 :        151 :   tree ptr = gimple_call_arg (call, 0);
    7069                 :        151 :   tree bit = gimple_call_arg (call, 1);
    7070                 :        151 :   tree flag = gimple_call_arg (call, 2);
    7071                 :        151 :   tree lhs = gimple_call_lhs (call);
    7072                 :        151 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7073                 :        151 :   machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
    7074                 :        151 :   enum rtx_code code;
    7075                 :        151 :   optab optab;
    7076                 :        151 :   class expand_operand ops[5];
    7077                 :            : 
    7078                 :        151 :   gcc_assert (flag_inline_atomics);
    7079                 :            : 
    7080                 :        151 :   if (gimple_call_num_args (call) == 4)
    7081                 :        103 :     model = get_memmodel (gimple_call_arg (call, 3));
    7082                 :            : 
    7083                 :        151 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7084                 :        151 :   rtx val = expand_expr_force_mode (bit, mode);
    7085                 :            : 
    7086                 :        151 :   switch (gimple_call_internal_fn (call))
    7087                 :            :     {
    7088                 :            :     case IFN_ATOMIC_BIT_TEST_AND_SET:
    7089                 :            :       code = IOR;
    7090                 :            :       optab = atomic_bit_test_and_set_optab;
    7091                 :            :       break;
    7092                 :            :     case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
    7093                 :            :       code = XOR;
    7094                 :            :       optab = atomic_bit_test_and_complement_optab;
    7095                 :            :       break;
    7096                 :            :     case IFN_ATOMIC_BIT_TEST_AND_RESET:
    7097                 :            :       code = AND;
    7098                 :            :       optab = atomic_bit_test_and_reset_optab;
    7099                 :            :       break;
    7100                 :          0 :     default:
    7101                 :          0 :       gcc_unreachable ();
    7102                 :            :     }
    7103                 :            : 
    7104                 :        151 :   if (lhs == NULL_TREE)
    7105                 :            :     {
    7106                 :          0 :       val = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7107                 :            :                                  val, NULL_RTX, true, OPTAB_DIRECT);
    7108                 :          0 :       if (code == AND)
    7109                 :          0 :         val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
    7110                 :          0 :       expand_atomic_fetch_op (const0_rtx, mem, val, code, model, false);
    7111                 :        151 :       return;
    7112                 :            :     }
    7113                 :            : 
    7114                 :        151 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7115                 :        151 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7116                 :        151 :   gcc_assert (icode != CODE_FOR_nothing);
    7117                 :        151 :   create_output_operand (&ops[0], target, mode);
    7118                 :        151 :   create_fixed_operand (&ops[1], mem);
    7119                 :        151 :   create_convert_operand_to (&ops[2], val, mode, true);
    7120                 :        151 :   create_integer_operand (&ops[3], model);
    7121                 :        151 :   create_integer_operand (&ops[4], integer_onep (flag));
    7122                 :        151 :   if (maybe_expand_insn (icode, 5, ops))
    7123                 :            :     return;
    7124                 :            : 
    7125                 :          0 :   rtx bitval = val;
    7126                 :          0 :   val = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7127                 :            :                              val, NULL_RTX, true, OPTAB_DIRECT);
    7128                 :          0 :   rtx maskval = val;
    7129                 :          0 :   if (code == AND)
    7130                 :          0 :     val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
    7131                 :          0 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
    7132                 :            :                                        code, model, false);
    7133                 :          0 :   if (integer_onep (flag))
    7134                 :            :     {
    7135                 :          0 :       result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
    7136                 :            :                                     NULL_RTX, true, OPTAB_DIRECT);
    7137                 :          0 :       result = expand_simple_binop (mode, AND, result, const1_rtx, target,
    7138                 :            :                                     true, OPTAB_DIRECT);
    7139                 :            :     }
    7140                 :            :   else
    7141                 :          0 :     result = expand_simple_binop (mode, AND, result, maskval, target, true,
    7142                 :            :                                   OPTAB_DIRECT);
    7143                 :          0 :   if (result != target)
    7144                 :          0 :     emit_move_insn (target, result);
    7145                 :            : }
    7146                 :            : 
    7147                 :            : /* Expand an atomic clear operation.
    7148                 :            :         void _atomic_clear (BOOL *obj, enum memmodel)
    7149                 :            :    EXP is the call expression.  */
    7150                 :            : 
    7151                 :            : static rtx
    7152                 :         51 : expand_builtin_atomic_clear (tree exp) 
    7153                 :            : {
    7154                 :         51 :   machine_mode mode;
    7155                 :         51 :   rtx mem, ret;
    7156                 :         51 :   enum memmodel model;
    7157                 :            : 
    7158                 :        102 :   mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7159                 :         51 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7160                 :         51 :   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7161                 :            : 
    7162                 :         51 :   if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
    7163                 :            :     {
    7164                 :          5 :       location_t loc
    7165                 :          5 :         = expansion_point_location_if_in_system_header (input_location);
    7166                 :          5 :       warning_at (loc, OPT_Winvalid_memory_model,
    7167                 :            :                   "invalid memory model for %<__atomic_store%>");
    7168                 :          5 :       model = MEMMODEL_SEQ_CST;
    7169                 :            :     }
    7170                 :            : 
    7171                 :            :   /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
    7172                 :            :      Failing that, a store is issued by __atomic_store.  The only way this can
    7173                 :            :      fail is if the bool type is larger than a word size.  Unlikely, but
    7174                 :            :      handle it anyway for completeness.  Assume a single threaded model since
    7175                 :            :      there is no atomic support in this case, and no barriers are required.  */
    7176                 :         51 :   ret = expand_atomic_store (mem, const0_rtx, model, true);
    7177                 :         51 :   if (!ret)
    7178                 :          0 :     emit_move_insn (mem, const0_rtx);
    7179                 :         51 :   return const0_rtx;
    7180                 :            : }
    7181                 :            : 
    7182                 :            : /* Expand an atomic test_and_set operation.
    7183                 :            :         bool _atomic_test_and_set (BOOL *obj, enum memmodel)
    7184                 :            :    EXP is the call expression.  */
    7185                 :            : 
    7186                 :            : static rtx
    7187                 :        239 : expand_builtin_atomic_test_and_set (tree exp, rtx target)
    7188                 :            : {
    7189                 :        239 :   rtx mem;
    7190                 :        239 :   enum memmodel model;
    7191                 :        239 :   machine_mode mode;
    7192                 :            : 
    7193                 :        478 :   mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7194                 :        239 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7195                 :        239 :   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7196                 :            : 
    7197                 :        239 :   return expand_atomic_test_and_set (target, mem, model);
    7198                 :            : }
    7199                 :            : 
    7200                 :            : 
    7201                 :            : /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
    7202                 :            :    this architecture.  If ARG1 is NULL, use typical alignment for size ARG0.  */
    7203                 :            : 
    7204                 :            : static tree
    7205                 :      25965 : fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
    7206                 :            : {
    7207                 :      25965 :   int size;
    7208                 :      25965 :   machine_mode mode;
    7209                 :      25965 :   unsigned int mode_align, type_align;
    7210                 :            : 
    7211                 :      25965 :   if (TREE_CODE (arg0) != INTEGER_CST)
    7212                 :            :     return NULL_TREE;
    7213                 :            : 
    7214                 :            :   /* We need a corresponding integer mode for the access to be lock-free.  */
    7215                 :      25871 :   size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
    7216                 :      77612 :   if (!int_mode_for_size (size, 0).exists (&mode))
    7217                 :          1 :     return boolean_false_node;
    7218                 :            : 
    7219                 :      25870 :   mode_align = GET_MODE_ALIGNMENT (mode);
    7220                 :            : 
    7221                 :      25870 :   if (TREE_CODE (arg1) == INTEGER_CST)
    7222                 :            :     {
    7223                 :      12761 :       unsigned HOST_WIDE_INT val = UINTVAL (expand_normal (arg1));
    7224                 :            : 
    7225                 :            :       /* Either this argument is null, or it's a fake pointer encoding
    7226                 :            :          the alignment of the object.  */
    7227                 :      12761 :       val = least_bit_hwi (val);
    7228                 :      12761 :       val *= BITS_PER_UNIT;
    7229                 :            : 
    7230                 :      12761 :       if (val == 0 || mode_align < val)
    7231                 :            :         type_align = mode_align;
    7232                 :            :       else
    7233                 :      12678 :         type_align = val;
    7234                 :            :     }
    7235                 :            :   else
    7236                 :            :     {
    7237                 :      13109 :       tree ttype = TREE_TYPE (arg1);
    7238                 :            : 
    7239                 :            :       /* This function is usually invoked and folded immediately by the front
    7240                 :            :          end before anything else has a chance to look at it.  The pointer
    7241                 :            :          parameter at this point is usually cast to a void *, so check for that
    7242                 :            :          and look past the cast.  */
    7243                 :      13109 :       if (CONVERT_EXPR_P (arg1)
    7244                 :      13068 :           && POINTER_TYPE_P (ttype)
    7245                 :      13068 :           && VOID_TYPE_P (TREE_TYPE (ttype))
    7246                 :      26177 :           && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
    7247                 :      13041 :         arg1 = TREE_OPERAND (arg1, 0);
    7248                 :            : 
    7249                 :      13109 :       ttype = TREE_TYPE (arg1);
    7250                 :      13109 :       gcc_assert (POINTER_TYPE_P (ttype));
    7251                 :            : 
    7252                 :            :       /* Get the underlying type of the object.  */
    7253                 :      13109 :       ttype = TREE_TYPE (ttype);
    7254                 :      13109 :       type_align = TYPE_ALIGN (ttype);
    7255                 :            :     }
    7256                 :            : 
    7257                 :            :   /* If the object has smaller alignment, the lock free routines cannot
    7258                 :            :      be used.  */
    7259                 :      25870 :   if (type_align < mode_align)
    7260                 :         91 :     return boolean_false_node;
    7261                 :            : 
    7262                 :            :   /* Check if a compare_and_swap pattern exists for the mode which represents
    7263                 :            :      the required size.  The pattern is not allowed to fail, so the existence
    7264                 :            :      of the pattern indicates support is present.  Also require that an
    7265                 :            :      atomic load exists for the required size.  */
    7266                 :      25779 :   if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
    7267                 :      25730 :     return boolean_true_node;
    7268                 :            :   else
    7269                 :         49 :     return boolean_false_node;
    7270                 :            : }
    7271                 :            : 
    7272                 :            : /* Return true if the parameters to call EXP represent an object which will
    7273                 :            :    always generate lock free instructions.  The first argument represents the
    7274                 :            :    size of the object, and the second parameter is a pointer to the object 
    7275                 :            :    itself.  If NULL is passed for the object, then the result is based on 
    7276                 :            :    typical alignment for an object of the specified size.  Otherwise return 
    7277                 :            :    false.  */
    7278                 :            : 
    7279                 :            : static rtx
    7280                 :          1 : expand_builtin_atomic_always_lock_free (tree exp)
    7281                 :            : {
    7282                 :          1 :   tree size;
    7283                 :          1 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7284                 :          1 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7285                 :            : 
    7286                 :          1 :   if (TREE_CODE (arg0) != INTEGER_CST)
    7287                 :            :     {
    7288                 :          1 :       error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
    7289                 :          1 :       return const0_rtx;
    7290                 :            :     }
    7291                 :            : 
    7292                 :          0 :   size = fold_builtin_atomic_always_lock_free (arg0, arg1);
    7293                 :          0 :   if (size == boolean_true_node)
    7294                 :          0 :     return const1_rtx;
    7295                 :          0 :   return const0_rtx;
    7296                 :            : }
    7297                 :            : 
    7298                 :            : /* Return a one or zero if it can be determined that object ARG1 of size ARG 
    7299                 :            :    is lock free on this architecture.  */
    7300                 :            : 
    7301                 :            : static tree
    7302                 :      25823 : fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
    7303                 :            : {
    7304                 :          0 :   if (!flag_inline_atomics)
    7305                 :            :     return NULL_TREE;
    7306                 :            :   
    7307                 :            :   /* If it isn't always lock free, don't generate a result.  */
    7308                 :      25814 :   if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
    7309                 :      25670 :     return boolean_true_node;
    7310                 :            : 
    7311                 :            :   return NULL_TREE;
    7312                 :            : }
    7313                 :            : 
    7314                 :            : /* Return true if the parameters to call EXP represent an object which will
    7315                 :            :    always generate lock free instructions.  The first argument represents the
    7316                 :            :    size of the object, and the second parameter is a pointer to the object 
    7317                 :            :    itself.  If NULL is passed for the object, then the result is based on 
    7318                 :            :    typical alignment for an object of the specified size.  Otherwise return 
    7319                 :            :    NULL*/
    7320                 :            : 
    7321                 :            : static rtx
    7322                 :          4 : expand_builtin_atomic_is_lock_free (tree exp)
    7323                 :            : {
    7324                 :          4 :   tree size;
    7325                 :          4 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7326                 :          4 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7327                 :            : 
    7328                 :          4 :   if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
    7329                 :            :     {
    7330                 :          0 :       error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
    7331                 :          0 :       return NULL_RTX;
    7332                 :            :     }
    7333                 :            : 
    7334                 :          4 :   if (!flag_inline_atomics)
    7335                 :            :     return NULL_RTX; 
    7336                 :            : 
    7337                 :            :   /* If the value is known at compile time, return the RTX for it.  */
    7338                 :          3 :   size = fold_builtin_atomic_is_lock_free (arg0, arg1);
    7339                 :          3 :   if (size == boolean_true_node)
    7340                 :          0 :     return const1_rtx;
    7341                 :            : 
    7342                 :            :   return NULL_RTX;
    7343                 :            : }
    7344                 :            : 
    7345                 :            : /* Expand the __atomic_thread_fence intrinsic:
    7346                 :            :         void __atomic_thread_fence (enum memmodel)
    7347                 :            :    EXP is the CALL_EXPR.  */
    7348                 :            : 
    7349                 :            : static void
    7350                 :        626 : expand_builtin_atomic_thread_fence (tree exp)
    7351                 :            : {
    7352                 :        626 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7353                 :        626 :   expand_mem_thread_fence (model);
    7354                 :        626 : }
    7355                 :            : 
    7356                 :            : /* Expand the __atomic_signal_fence intrinsic:
    7357                 :            :         void __atomic_signal_fence (enum memmodel)
    7358                 :            :    EXP is the CALL_EXPR.  */
    7359                 :            : 
    7360                 :            : static void
    7361                 :         58 : expand_builtin_atomic_signal_fence (tree exp)
    7362                 :            : {
    7363                 :         58 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7364                 :         58 :   expand_mem_signal_fence (model);
    7365                 :         58 : }
    7366                 :            : 
    7367                 :            : /* Expand the __sync_synchronize intrinsic.  */
    7368                 :            : 
    7369                 :            : static void
    7370                 :        212 : expand_builtin_sync_synchronize (void)
    7371                 :            : {
    7372                 :          0 :   expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
    7373                 :          0 : }
    7374                 :            : 
    7375                 :            : static rtx
    7376                 :          0 : expand_builtin_thread_pointer (tree exp, rtx target)
    7377                 :            : {
    7378                 :          0 :   enum insn_code icode;
    7379                 :          0 :   if (!validate_arglist (exp, VOID_TYPE))
    7380                 :          0 :     return const0_rtx;
    7381                 :          0 :   icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
    7382                 :          0 :   if (icode != CODE_FOR_nothing)
    7383                 :            :     {
    7384                 :          0 :       class expand_operand op;
    7385                 :            :       /* If the target is not sutitable then create a new target. */
    7386                 :          0 :       if (target == NULL_RTX
    7387                 :          0 :           || !REG_P (target)
    7388                 :          0 :           || GET_MODE (target) != Pmode)
    7389                 :          0 :         target = gen_reg_rtx (Pmode);
    7390                 :          0 :       create_output_operand (&op, target, Pmode);
    7391                 :          0 :       expand_insn (icode, 1, &op);
    7392                 :          0 :       return target;
    7393                 :            :     }
    7394                 :          0 :   error ("%<__builtin_thread_pointer%> is not supported on this target");
    7395                 :          0 :   return const0_rtx;
    7396                 :            : }
    7397                 :            : 
    7398                 :            : static void
    7399                 :          0 : expand_builtin_set_thread_pointer (tree exp)
    7400                 :            : {
    7401                 :          0 :   enum insn_code icode;
    7402                 :          0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    7403                 :            :     return;
    7404                 :          0 :   icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
    7405                 :          0 :   if (icode != CODE_FOR_nothing)
    7406                 :            :     {
    7407                 :          0 :       class expand_operand op;
    7408                 :          0 :       rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
    7409                 :          0 :                              Pmode, EXPAND_NORMAL);      
    7410                 :          0 :       create_input_operand (&op, val, Pmode);
    7411                 :          0 :       expand_insn (icode, 1, &op);
    7412                 :          0 :       return;
    7413                 :            :     }
    7414                 :          0 :   error ("%<__builtin_set_thread_pointer%> is not supported on this target");
    7415                 :            : }
    7416                 :            : 
    7417                 :            : 
    7418                 :            : /* Emit code to restore the current value of stack.  */
    7419                 :            : 
    7420                 :            : static void
    7421                 :       1214 : expand_stack_restore (tree var)
    7422                 :            : {
    7423                 :       1214 :   rtx_insn *prev;
    7424                 :       1214 :   rtx sa = expand_normal (var);
    7425                 :            : 
    7426                 :       2428 :   sa = convert_memory_address (Pmode, sa);
    7427                 :            : 
    7428                 :       1214 :   prev = get_last_insn ();
    7429                 :       1214 :   emit_stack_restore (SAVE_BLOCK, sa);
    7430                 :            : 
    7431                 :       1214 :   record_new_stack_level ();
    7432                 :            : 
    7433                 :       1214 :   fixup_args_size_notes (prev, get_last_insn (), 0);
    7434                 :       1214 : }
    7435                 :            : 
    7436                 :            : /* Emit code to save the current value of stack.  */
    7437                 :            : 
    7438                 :            : static rtx
    7439                 :       1355 : expand_stack_save (void)
    7440                 :            : {
    7441                 :       1355 :   rtx ret = NULL_RTX;
    7442                 :            : 
    7443                 :          0 :   emit_stack_save (SAVE_BLOCK, &ret);
    7444                 :       1355 :   return ret;
    7445                 :            : }
    7446                 :            : 
    7447                 :            : /* Emit code to get the openacc gang, worker or vector id or size.  */
    7448                 :            : 
    7449                 :            : static rtx
    7450                 :        272 : expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
    7451                 :            : {
    7452                 :        272 :   const char *name;
    7453                 :        272 :   rtx fallback_retval;
    7454                 :        272 :   rtx_insn *(*gen_fn) (rtx, rtx);
    7455                 :        272 :   switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
    7456                 :            :     {
    7457                 :        116 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    7458                 :        116 :       name = "__builtin_goacc_parlevel_id";
    7459                 :        116 :       fallback_retval = const0_rtx;
    7460                 :        116 :       gen_fn = targetm.gen_oacc_dim_pos;
    7461                 :        116 :       break;
    7462                 :        156 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    7463                 :        156 :       name = "__builtin_goacc_parlevel_size";
    7464                 :        156 :       fallback_retval = const1_rtx;
    7465                 :        156 :       gen_fn = targetm.gen_oacc_dim_size;
    7466                 :        156 :       break;
    7467                 :          0 :     default:
    7468                 :          0 :       gcc_unreachable ();
    7469                 :            :     }
    7470                 :            : 
    7471                 :        272 :   if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
    7472                 :            :     {
    7473                 :         10 :       error ("%qs only supported in OpenACC code", name);
    7474                 :         10 :       return const0_rtx;
    7475                 :            :     }
    7476                 :            : 
    7477                 :        262 :   tree arg = CALL_EXPR_ARG (exp, 0);
    7478                 :        262 :   if (TREE_CODE (arg) != INTEGER_CST)
    7479                 :            :     {
    7480                 :         10 :       error ("non-constant argument 0 to %qs", name);
    7481                 :         10 :       return const0_rtx;
    7482                 :            :     }
    7483                 :            : 
    7484                 :        252 :   int dim = TREE_INT_CST_LOW (arg);
    7485                 :        252 :   switch (dim)
    7486                 :            :     {
    7487                 :        232 :     case GOMP_DIM_GANG:
    7488                 :        232 :     case GOMP_DIM_WORKER:
    7489                 :        232 :     case GOMP_DIM_VECTOR:
    7490                 :        232 :       break;
    7491                 :         20 :     default:
    7492                 :         20 :       error ("illegal argument 0 to %qs", name);
    7493                 :         20 :       return const0_rtx;
    7494                 :            :     }
    7495                 :            : 
    7496                 :        232 :   if (ignore)
    7497                 :            :     return target;
    7498                 :            : 
    7499                 :        112 :   if (target == NULL_RTX)
    7500                 :          0 :     target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    7501                 :            : 
    7502                 :        112 :   if (!targetm.have_oacc_dim_size ())
    7503                 :            :     {
    7504                 :        112 :       emit_move_insn (target, fallback_retval);
    7505                 :        112 :       return target;
    7506                 :            :     }
    7507                 :            : 
    7508                 :          0 :   rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
    7509                 :          0 :   emit_insn (gen_fn (reg, GEN_INT (dim)));
    7510                 :          0 :   if (reg != target)
    7511                 :          0 :     emit_move_insn (target, reg);
    7512                 :            : 
    7513                 :            :   return target;
    7514                 :            : }
    7515                 :            : 
    7516                 :            : /* Expand a string compare operation using a sequence of char comparison
    7517                 :            :    to get rid of the calling overhead, with result going to TARGET if
    7518                 :            :    that's convenient.
    7519                 :            : 
    7520                 :            :    VAR_STR is the variable string source;
    7521                 :            :    CONST_STR is the constant string source;
    7522                 :            :    LENGTH is the number of chars to compare;
    7523                 :            :    CONST_STR_N indicates which source string is the constant string;
    7524                 :            :    IS_MEMCMP indicates whether it's a memcmp or strcmp.
    7525                 :            :   
    7526                 :            :    to: (assume const_str_n is 2, i.e., arg2 is a constant string)
    7527                 :            : 
    7528                 :            :    target = (int) (unsigned char) var_str[0]
    7529                 :            :             - (int) (unsigned char) const_str[0];
    7530                 :            :    if (target != 0)
    7531                 :            :      goto ne_label;
    7532                 :            :      ...
    7533                 :            :    target = (int) (unsigned char) var_str[length - 2]
    7534                 :            :             - (int) (unsigned char) const_str[length - 2];
    7535                 :            :    if (target != 0)
    7536                 :            :      goto ne_label;
    7537                 :            :    target = (int) (unsigned char) var_str[length - 1]
    7538                 :            :             - (int) (unsigned char) const_str[length - 1];
    7539                 :            :    ne_label:
    7540                 :            :   */
    7541                 :            : 
    7542                 :            : static rtx
    7543                 :       3975 : inline_string_cmp (rtx target, tree var_str, const char *const_str,
    7544                 :            :                    unsigned HOST_WIDE_INT length,
    7545                 :            :                    int const_str_n, machine_mode mode)
    7546                 :            : {
    7547                 :       3975 :   HOST_WIDE_INT offset = 0;
    7548                 :       3975 :   rtx var_rtx_array
    7549                 :       3975 :     = get_memory_rtx (var_str, build_int_cst (unsigned_type_node,length));
    7550                 :       3975 :   rtx var_rtx = NULL_RTX;
    7551                 :       3975 :   rtx const_rtx = NULL_RTX;
    7552                 :       3975 :   rtx result = target ? target : gen_reg_rtx (mode);
    7553                 :       3975 :   rtx_code_label *ne_label = gen_label_rtx ();
    7554                 :       3975 :   tree unit_type_node = unsigned_char_type_node;
    7555                 :       3975 :   scalar_int_mode unit_mode
    7556                 :       3975 :     = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
    7557                 :            : 
    7558                 :       3975 :   start_sequence ();
    7559                 :            : 
    7560                 :      14299 :   for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
    7561                 :            :     {
    7562                 :      10324 :       var_rtx
    7563                 :      10324 :         = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
    7564                 :      10324 :       const_rtx = c_readstr (const_str + offset, unit_mode);
    7565                 :      10324 :       rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
    7566                 :      10324 :       rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
    7567                 :            : 
    7568                 :      10324 :       op0 = convert_modes (mode, unit_mode, op0, 1);
    7569                 :      10324 :       op1 = convert_modes (mode, unit_mode, op1, 1);
    7570                 :      10324 :       result = expand_simple_binop (mode, MINUS, op0, op1,
    7571                 :            :                                     result, 1, OPTAB_WIDEN);
    7572                 :      10324 :       if (i < length - 1)
    7573                 :       6349 :         emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
    7574                 :            :                                  mode, true, ne_label);
    7575                 :      20648 :       offset += GET_MODE_SIZE (unit_mode);
    7576                 :            :     }
    7577                 :            : 
    7578                 :       3975 :   emit_label (ne_label);
    7579                 :       3975 :   rtx_insn *insns = get_insns ();
    7580                 :       3975 :   end_sequence ();
    7581                 :       3975 :   emit_insn (insns);
    7582                 :            : 
    7583                 :       3975 :   return result;
    7584                 :            : }
    7585                 :            : 
    7586                 :            : /* Inline expansion a call to str(n)cmp, with result going to
    7587                 :            :    TARGET if that's convenient.
    7588                 :            :    If the call is not been inlined, return NULL_RTX.  */
    7589                 :            : static rtx
    7590                 :      67303 : inline_expand_builtin_string_cmp (tree exp, rtx target)
    7591                 :            : {
    7592                 :      67303 :   tree fndecl = get_callee_fndecl (exp);
    7593                 :      67303 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7594                 :      67303 :   unsigned HOST_WIDE_INT length = 0;
    7595                 :      67303 :   bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
    7596                 :            : 
    7597                 :            :   /* Do NOT apply this inlining expansion when optimizing for size or 
    7598                 :            :      optimization level below 2.  */
    7599                 :      67303 :   if (optimize < 2 || optimize_insn_for_size_p ())
    7600                 :      33559 :     return NULL_RTX;
    7601                 :            : 
    7602                 :      33744 :   gcc_checking_assert (fcode == BUILT_IN_STRCMP
    7603                 :            :                        || fcode == BUILT_IN_STRNCMP
    7604                 :            :                        || fcode == BUILT_IN_MEMCMP);
    7605                 :            : 
    7606                 :            :   /* On a target where the type of the call (int) has same or narrower presicion
    7607                 :            :      than unsigned char, give up the inlining expansion.  */
    7608                 :      33744 :   if (TYPE_PRECISION (unsigned_char_type_node)
    7609                 :      33744 :       >= TYPE_PRECISION (TREE_TYPE (exp)))
    7610                 :            :     return NULL_RTX;
    7611                 :            : 
    7612                 :      33744 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    7613                 :      33744 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    7614                 :      33744 :   tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
    7615                 :            : 
    7616                 :      33744 :   unsigned HOST_WIDE_INT len1 = 0;
    7617                 :      33744 :   unsigned HOST_WIDE_INT len2 = 0;
    7618                 :      33744 :   unsigned HOST_WIDE_INT len3 = 0;
    7619                 :            : 
    7620                 :      33744 :   const char *src_str1 = c_getstr (arg1, &len1);
    7621                 :      33744 :   const char *src_str2 = c_getstr (arg2, &len2);
    7622                 :            : 
    7623                 :            :   /* If neither strings is constant string, the call is not qualify.  */
    7624                 :      33744 :   if (!src_str1 && !src_str2)
    7625                 :            :     return NULL_RTX;
    7626                 :            : 
    7627                 :            :   /* For strncmp, if the length is not a const, not qualify.  */
    7628                 :      16888 :   if (is_ncmp)
    7629                 :            :     {
    7630                 :      15259 :       if (!tree_fits_uhwi_p (len3_tree))
    7631                 :            :         return NULL_RTX;
    7632                 :            :       else
    7633                 :      15038 :         len3 = tree_to_uhwi (len3_tree);
    7634                 :            :     }
    7635                 :            : 
    7636                 :      16667 :   if (src_str1 != NULL)
    7637                 :        269 :     len1 = strnlen (src_str1, len1) + 1;
    7638                 :            : 
    7639                 :      16667 :   if (src_str2 != NULL)
    7640                 :      16398 :     len2 = strnlen (src_str2, len2) + 1;
    7641                 :            : 
    7642                 :      16667 :   int const_str_n = 0;
    7643                 :      16667 :   if (!len1)
    7644                 :            :     const_str_n = 2;
    7645                 :        269 :   else if (!len2)
    7646                 :            :     const_str_n = 1;
    7647                 :          0 :   else if (len2 > len1)
    7648                 :            :     const_str_n = 1;
    7649                 :            :   else
    7650                 :            :     const_str_n = 2;
    7651                 :            : 
    7652                 :          0 :   gcc_checking_assert (const_str_n > 0);
    7653                 :      16667 :   length = (const_str_n == 1) ? len1 : len2;
    7654                 :            : 
    7655                 :      16667 :   if (is_ncmp && len3 < length)
    7656                 :      14992 :     length = len3;
    7657                 :            : 
    7658                 :            :   /* If the length of the comparision is larger than the threshold,
    7659                 :            :      do nothing.  */
    7660                 :      16667 :   if (length > (unsigned HOST_WIDE_INT)
    7661                 :      16667 :                param_builtin_string_cmp_inline_length)
    7662                 :            :     return NULL_RTX;
    7663                 :            : 
    7664                 :       3975 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    7665                 :            : 
    7666                 :            :   /* Now, start inline expansion the call.  */
    7667                 :      11827 :   return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
    7668                 :            :                             (const_str_n == 1) ? src_str1 : src_str2, length,
    7669                 :       3975 :                             const_str_n, mode);
    7670                 :            : }
    7671                 :            : 
    7672                 :            : /* Expand a call to __builtin_speculation_safe_value_<N>.  MODE
    7673                 :            :    represents the size of the first argument to that call, or VOIDmode
    7674                 :            :    if the argument is a pointer.  IGNORE will be true if the result
    7675                 :            :    isn't used.  */
    7676                 :            : static rtx
    7677                 :         41 : expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
    7678                 :            :                                bool ignore)
    7679                 :            : {
    7680                 :         41 :   rtx val, failsafe;
    7681                 :         41 :   unsigned nargs = call_expr_nargs (exp);
    7682                 :            : 
    7683                 :         41 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7684                 :            : 
    7685                 :         41 :   if (mode == VOIDmode)
    7686                 :            :     {
    7687                 :          5 :       mode = TYPE_MODE (TREE_TYPE (arg0));
    7688                 :          5 :       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
    7689                 :            :     }
    7690                 :            : 
    7691                 :         41 :   val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    7692                 :            : 
    7693                 :            :   /* An optional second argument can be used as a failsafe value on
    7694                 :            :      some machines.  If it isn't present, then the failsafe value is
    7695                 :            :      assumed to be 0.  */
    7696                 :         41 :   if (nargs > 1)
    7697                 :            :     {
    7698                 :          5 :       tree arg1 = CALL_EXPR_ARG (exp, 1);
    7699                 :          5 :       failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
    7700                 :            :     }
    7701                 :            :   else
    7702                 :         36 :     failsafe = const0_rtx;
    7703                 :            : 
    7704                 :            :   /* If the result isn't used, the behavior is undefined.  It would be
    7705                 :            :      nice to emit a warning here, but path splitting means this might
    7706                 :            :      happen with legitimate code.  So simply drop the builtin
    7707                 :            :      expansion in that case; we've handled any side-effects above.  */
    7708                 :         41 :   if (ignore)
    7709                 :          0 :     return const0_rtx;
    7710                 :            : 
    7711                 :            :   /* If we don't have a suitable target, create one to hold the result.  */
    7712                 :         41 :   if (target == NULL || GET_MODE (target) != mode)
    7713                 :          0 :     target = gen_reg_rtx (mode);
    7714                 :            : 
    7715                 :         41 :   if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
    7716                 :         10 :     val = convert_modes (mode, VOIDmode, val, false);
    7717                 :            : 
    7718                 :         41 :   return targetm.speculation_safe_value (mode, target, val, failsafe);
    7719                 :            : }
    7720                 :            : 
    7721                 :            : /* Expand an expression EXP that calls a built-in function,
    7722                 :            :    with result going to TARGET if that's convenient
    7723                 :            :    (and in mode MODE if that's convenient).
    7724                 :            :    SUBTARGET may be used as the target for computing one of EXP's operands.
    7725                 :            :    IGNORE is nonzero if the value is to be ignored.  */
    7726                 :            : 
    7727                 :            : rtx
    7728                 :    1254750 : expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
    7729                 :            :                 int ignore)
    7730                 :            : {
    7731                 :    1254750 :   tree fndecl = get_callee_fndecl (exp);
    7732                 :    1254750 :   machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
    7733                 :    1254750 :   int flags;
    7734                 :            : 
    7735                 :    1254750 :   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
    7736                 :     144986 :     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
    7737                 :            : 
    7738                 :            :   /* When ASan is enabled, we don't want to expand some memory/string
    7739                 :            :      builtins and rely on libsanitizer's hooks.  This allows us to avoid
    7740                 :            :      redundant checks and be sure, that possible overflow will be detected
    7741                 :            :      by ASan.  */
    7742                 :            : 
    7743                 :    1109760 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7744                 :    1109760 :   if ((flag_sanitize & SANITIZE_ADDRESS) && asan_intercepted_p (fcode))
    7745                 :        378 :     return expand_call (exp, target, ignore);
    7746                 :            : 
    7747                 :            :   /* When not optimizing, generate calls to library functions for a certain
    7748                 :            :      set of builtins.  */
    7749                 :    1109380 :   if (!optimize
    7750                 :     268920 :       && !called_as_built_in (fndecl)
    7751                 :      88220 :       && fcode != BUILT_IN_FORK
    7752                 :      88220 :       && fcode != BUILT_IN_EXECL
    7753                 :      88213 :       && fcode != BUILT_IN_EXECV
    7754                 :      88213 :       && fcode != BUILT_IN_EXECLP
    7755                 :      88213 :       && fcode != BUILT_IN_EXECLE
    7756                 :      88213 :       && fcode != BUILT_IN_EXECVP
    7757                 :      88213 :       && fcode != BUILT_IN_EXECVE
    7758                 :      88209 :       && !ALLOCA_FUNCTION_CODE_P (fcode)
    7759                 :    1197570 :       && fcode != BUILT_IN_FREE)