Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Expand builtin functions.
      2  1.1  mrg    Copyright (C) 1988-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of GCC.
      5  1.1  mrg 
      6  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      7  1.1  mrg the terms of the GNU General Public License as published by the Free
      8  1.1  mrg Software Foundation; either version 3, or (at your option) any later
      9  1.1  mrg version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  1.1  mrg for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License
     17  1.1  mrg along with GCC; see the file COPYING3.  If not see
     18  1.1  mrg <http://www.gnu.org/licenses/>.  */
     19  1.1  mrg 
     20  1.1  mrg /* Legacy warning!  Please add no further builtin simplifications here
     21  1.1  mrg    (apart from pure constant folding) - builtin simplifications should go
     22  1.1  mrg    to match.pd or gimple-fold.cc instead.  */
     23  1.1  mrg 
     24  1.1  mrg #include "config.h"
     25  1.1  mrg #include "system.h"
     26  1.1  mrg #include "coretypes.h"
     27  1.1  mrg #include "backend.h"
     28  1.1  mrg #include "target.h"
     29  1.1  mrg #include "rtl.h"
     30  1.1  mrg #include "tree.h"
     31  1.1  mrg #include "memmodel.h"
     32  1.1  mrg #include "gimple.h"
     33  1.1  mrg #include "predict.h"
     34  1.1  mrg #include "tm_p.h"
     35  1.1  mrg #include "stringpool.h"
     36  1.1  mrg #include "tree-vrp.h"
     37  1.1  mrg #include "tree-ssanames.h"
     38  1.1  mrg #include "expmed.h"
     39  1.1  mrg #include "optabs.h"
     40  1.1  mrg #include "emit-rtl.h"
     41  1.1  mrg #include "recog.h"
     42  1.1  mrg #include "diagnostic-core.h"
     43  1.1  mrg #include "alias.h"
     44  1.1  mrg #include "fold-const.h"
     45  1.1  mrg #include "fold-const-call.h"
     46  1.1  mrg #include "gimple-ssa-warn-access.h"
     47  1.1  mrg #include "stor-layout.h"
     48  1.1  mrg #include "calls.h"
     49  1.1  mrg #include "varasm.h"
     50  1.1  mrg #include "tree-object-size.h"
     51  1.1  mrg #include "tree-ssa-strlen.h"
     52  1.1  mrg #include "realmpfr.h"
     53  1.1  mrg #include "cfgrtl.h"
     54  1.1  mrg #include "except.h"
     55  1.1  mrg #include "dojump.h"
     56  1.1  mrg #include "explow.h"
     57  1.1  mrg #include "stmt.h"
     58  1.1  mrg #include "expr.h"
     59  1.1  mrg #include "libfuncs.h"
     60  1.1  mrg #include "output.h"
     61  1.1  mrg #include "typeclass.h"
     62  1.1  mrg #include "langhooks.h"
     63  1.1  mrg #include "value-prof.h"
     64  1.1  mrg #include "builtins.h"
     65  1.1  mrg #include "stringpool.h"
     66  1.1  mrg #include "attribs.h"
     67  1.1  mrg #include "asan.h"
     68  1.1  mrg #include "internal-fn.h"
     69  1.1  mrg #include "case-cfn-macros.h"
     70  1.1  mrg #include "gimple-fold.h"
     71  1.1  mrg #include "intl.h"
     72  1.1  mrg #include "file-prefix-map.h" /* remap_macro_filename()  */
     73  1.1  mrg #include "gomp-constants.h"
     74  1.1  mrg #include "omp-general.h"
     75  1.1  mrg #include "tree-dfa.h"
     76  1.1  mrg #include "gimple-iterator.h"
     77  1.1  mrg #include "gimple-ssa.h"
     78  1.1  mrg #include "tree-ssa-live.h"
     79  1.1  mrg #include "tree-outof-ssa.h"
     80  1.1  mrg #include "attr-fnspec.h"
     81  1.1  mrg #include "demangle.h"
     82  1.1  mrg #include "gimple-range.h"
     83  1.1  mrg #include "pointer-query.h"
     84  1.1  mrg 
     85  1.1  mrg struct target_builtins default_target_builtins;
     86  1.1  mrg #if SWITCHABLE_TARGET
     87  1.1  mrg struct target_builtins *this_target_builtins = &default_target_builtins;
     88  1.1  mrg #endif
     89  1.1  mrg 
     90  1.1  mrg /* Define the names of the builtin function types and codes.  */
     91  1.1  mrg const char *const built_in_class_names[BUILT_IN_LAST]
     92  1.1  mrg   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
     93  1.1  mrg 
     94  1.1  mrg #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
     95  1.1  mrg const char * built_in_names[(int) END_BUILTINS] =
     96  1.1  mrg {
     97  1.1  mrg #include "builtins.def"
     98  1.1  mrg };
     99  1.1  mrg 
    100  1.1  mrg /* Setup an array of builtin_info_type, make sure each element decl is
    101  1.1  mrg    initialized to NULL_TREE.  */
    102  1.1  mrg builtin_info_type builtin_info[(int)END_BUILTINS];
    103  1.1  mrg 
    104  1.1  mrg /* Non-zero if __builtin_constant_p should be folded right away.  */
    105  1.1  mrg bool force_folding_builtin_constant_p;
    106  1.1  mrg 
    107  1.1  mrg static int target_char_cast (tree, char *);
    108  1.1  mrg static int apply_args_size (void);
    109  1.1  mrg static int apply_result_size (void);
    110  1.1  mrg static rtx result_vector (int, rtx);
    111  1.1  mrg static void expand_builtin_prefetch (tree);
    112  1.1  mrg static rtx expand_builtin_apply_args (void);
    113  1.1  mrg static rtx expand_builtin_apply_args_1 (void);
    114  1.1  mrg static rtx expand_builtin_apply (rtx, rtx, rtx);
    115  1.1  mrg static void expand_builtin_return (rtx);
    116  1.1  mrg static enum type_class type_to_class (tree);
    117  1.1  mrg static rtx expand_builtin_classify_type (tree);
    118  1.1  mrg static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
    119  1.1  mrg static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
    120  1.1  mrg static rtx expand_builtin_interclass_mathfn (tree, rtx);
    121  1.1  mrg static rtx expand_builtin_sincos (tree);
    122  1.1  mrg static rtx expand_builtin_fegetround (tree, rtx, machine_mode);
    123  1.1  mrg static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode,
    124  1.1  mrg 						  optab);
    125  1.1  mrg static rtx expand_builtin_cexpi (tree, rtx);
    126  1.1  mrg static rtx expand_builtin_int_roundingfn (tree, rtx);
    127  1.1  mrg static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
    128  1.1  mrg static rtx expand_builtin_next_arg (void);
    129  1.1  mrg static rtx expand_builtin_va_start (tree);
    130  1.1  mrg static rtx expand_builtin_va_end (tree);
    131  1.1  mrg static rtx expand_builtin_va_copy (tree);
    132  1.1  mrg static rtx inline_expand_builtin_bytecmp (tree, rtx);
    133  1.1  mrg static rtx expand_builtin_strcmp (tree, rtx);
    134  1.1  mrg static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
    135  1.1  mrg static rtx expand_builtin_memcpy (tree, rtx);
    136  1.1  mrg static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
    137  1.1  mrg 					    rtx target, tree exp,
    138  1.1  mrg 					    memop_ret retmode,
    139  1.1  mrg 					    bool might_overlap);
    140  1.1  mrg static rtx expand_builtin_memmove (tree, rtx);
    141  1.1  mrg static rtx expand_builtin_mempcpy (tree, rtx);
    142  1.1  mrg static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
    143  1.1  mrg static rtx expand_builtin_strcpy (tree, rtx);
    144  1.1  mrg static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
    145  1.1  mrg static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
    146  1.1  mrg static rtx expand_builtin_strncpy (tree, rtx);
    147  1.1  mrg static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
    148  1.1  mrg static rtx expand_builtin_bzero (tree);
    149  1.1  mrg static rtx expand_builtin_strlen (tree, rtx, machine_mode);
    150  1.1  mrg static rtx expand_builtin_strnlen (tree, rtx, machine_mode);
    151  1.1  mrg static rtx expand_builtin_alloca (tree);
    152  1.1  mrg static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
    153  1.1  mrg static rtx expand_builtin_frame_address (tree, tree);
    154  1.1  mrg static tree stabilize_va_list_loc (location_t, tree, int);
    155  1.1  mrg static rtx expand_builtin_expect (tree, rtx);
    156  1.1  mrg static rtx expand_builtin_expect_with_probability (tree, rtx);
    157  1.1  mrg static tree fold_builtin_constant_p (tree);
    158  1.1  mrg static tree fold_builtin_classify_type (tree);
    159  1.1  mrg static tree fold_builtin_strlen (location_t, tree, tree, tree);
    160  1.1  mrg static tree fold_builtin_inf (location_t, tree, int);
    161  1.1  mrg static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
    162  1.1  mrg static bool validate_arg (const_tree, enum tree_code code);
    163  1.1  mrg static rtx expand_builtin_fabs (tree, rtx, rtx);
    164  1.1  mrg static rtx expand_builtin_signbit (tree, rtx);
    165  1.1  mrg static tree fold_builtin_memcmp (location_t, tree, tree, tree);
    166  1.1  mrg static tree fold_builtin_isascii (location_t, tree);
    167  1.1  mrg static tree fold_builtin_toascii (location_t, tree);
    168  1.1  mrg static tree fold_builtin_isdigit (location_t, tree);
    169  1.1  mrg static tree fold_builtin_fabs (location_t, tree, tree);
    170  1.1  mrg static tree fold_builtin_abs (location_t, tree, tree);
    171  1.1  mrg static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
    172  1.1  mrg 					enum tree_code);
    173  1.1  mrg static tree fold_builtin_varargs (location_t, tree, tree*, int);
    174  1.1  mrg 
    175  1.1  mrg static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
    176  1.1  mrg static tree fold_builtin_strspn (location_t, tree, tree, tree);
    177  1.1  mrg static tree fold_builtin_strcspn (location_t, tree, tree, tree);
    178  1.1  mrg 
    179  1.1  mrg static rtx expand_builtin_object_size (tree);
    180  1.1  mrg static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
    181  1.1  mrg 				      enum built_in_function);
    182  1.1  mrg static void maybe_emit_chk_warning (tree, enum built_in_function);
    183  1.1  mrg static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
    184  1.1  mrg static tree fold_builtin_object_size (tree, tree, enum built_in_function);
    185  1.1  mrg 
    186  1.1  mrg unsigned HOST_WIDE_INT target_newline;
    187  1.1  mrg unsigned HOST_WIDE_INT target_percent;
    188  1.1  mrg static unsigned HOST_WIDE_INT target_c;
    189  1.1  mrg static unsigned HOST_WIDE_INT target_s;
    190  1.1  mrg char target_percent_c[3];
    191  1.1  mrg char target_percent_s[3];
    192  1.1  mrg char target_percent_s_newline[4];
    193  1.1  mrg static tree do_mpfr_remquo (tree, tree, tree);
    194  1.1  mrg static tree do_mpfr_lgamma_r (tree, tree, tree);
    195  1.1  mrg static void expand_builtin_sync_synchronize (void);
    196  1.1  mrg 
    197  1.1  mrg /* Return true if NAME starts with __builtin_ or __sync_.  */
    198  1.1  mrg 
    199  1.1  mrg static bool
    200  1.1  mrg is_builtin_name (const char *name)
    201  1.1  mrg {
    202  1.1  mrg   return (startswith (name, "__builtin_")
    203  1.1  mrg 	  || startswith (name, "__sync_")
    204  1.1  mrg 	  || startswith (name, "__atomic_"));
    205  1.1  mrg }
    206  1.1  mrg 
    207  1.1  mrg /* Return true if NODE should be considered for inline expansion regardless
    208  1.1  mrg    of the optimization level.  This means whenever a function is invoked with
    209  1.1  mrg    its "internal" name, which normally contains the prefix "__builtin".  */
    210  1.1  mrg 
    211  1.1  mrg bool
    212  1.1  mrg called_as_built_in (tree node)
    213  1.1  mrg {
    214  1.1  mrg   /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
    215  1.1  mrg      we want the name used to call the function, not the name it
    216  1.1  mrg      will have. */
    217  1.1  mrg   const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
    218  1.1  mrg   return is_builtin_name (name);
    219  1.1  mrg }
    220  1.1  mrg 
    221  1.1  mrg /* Compute values M and N such that M divides (address of EXP - N) and such
    222  1.1  mrg    that N < M.  If these numbers can be determined, store M in alignp and N in
    223  1.1  mrg    *BITPOSP and return true.  Otherwise return false and store BITS_PER_UNIT to
    224  1.1  mrg    *alignp and any bit-offset to *bitposp.
    225  1.1  mrg 
    226  1.1  mrg    Note that the address (and thus the alignment) computed here is based
    227  1.1  mrg    on the address to which a symbol resolves, whereas DECL_ALIGN is based
    228  1.1  mrg    on the address at which an object is actually located.  These two
    229  1.1  mrg    addresses are not always the same.  For example, on ARM targets,
    230  1.1  mrg    the address &foo of a Thumb function foo() has the lowest bit set,
    231  1.1  mrg    whereas foo() itself starts on an even address.
    232  1.1  mrg 
    233  1.1  mrg    If ADDR_P is true we are taking the address of the memory reference EXP
    234  1.1  mrg    and thus cannot rely on the access taking place.  */
    235  1.1  mrg 
    236  1.1  mrg bool
    237  1.1  mrg get_object_alignment_2 (tree exp, unsigned int *alignp,
    238  1.1  mrg 			unsigned HOST_WIDE_INT *bitposp, bool addr_p)
    239  1.1  mrg {
    240  1.1  mrg   poly_int64 bitsize, bitpos;
    241  1.1  mrg   tree offset;
    242  1.1  mrg   machine_mode mode;
    243  1.1  mrg   int unsignedp, reversep, volatilep;
    244  1.1  mrg   unsigned int align = BITS_PER_UNIT;
    245  1.1  mrg   bool known_alignment = false;
    246  1.1  mrg 
    247  1.1  mrg   /* Get the innermost object and the constant (bitpos) and possibly
    248  1.1  mrg      variable (offset) offset of the access.  */
    249  1.1  mrg   exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
    250  1.1  mrg 			     &unsignedp, &reversep, &volatilep);
    251  1.1  mrg 
    252  1.1  mrg   /* Extract alignment information from the innermost object and
    253  1.1  mrg      possibly adjust bitpos and offset.  */
    254  1.1  mrg   if (TREE_CODE (exp) == FUNCTION_DECL)
    255  1.1  mrg     {
    256  1.1  mrg       /* Function addresses can encode extra information besides their
    257  1.1  mrg 	 alignment.  However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
    258  1.1  mrg 	 allows the low bit to be used as a virtual bit, we know
    259  1.1  mrg 	 that the address itself must be at least 2-byte aligned.  */
    260  1.1  mrg       if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
    261  1.1  mrg 	align = 2 * BITS_PER_UNIT;
    262  1.1  mrg     }
    263  1.1  mrg   else if (TREE_CODE (exp) == LABEL_DECL)
    264  1.1  mrg     ;
    265  1.1  mrg   else if (TREE_CODE (exp) == CONST_DECL)
    266  1.1  mrg     {
    267  1.1  mrg       /* The alignment of a CONST_DECL is determined by its initializer.  */
    268  1.1  mrg       exp = DECL_INITIAL (exp);
    269  1.1  mrg       align = TYPE_ALIGN (TREE_TYPE (exp));
    270  1.1  mrg       if (CONSTANT_CLASS_P (exp))
    271  1.1  mrg 	align = targetm.constant_alignment (exp, align);
    272  1.1  mrg 
    273  1.1  mrg       known_alignment = true;
    274  1.1  mrg     }
    275  1.1  mrg   else if (DECL_P (exp))
    276  1.1  mrg     {
    277  1.1  mrg       align = DECL_ALIGN (exp);
    278  1.1  mrg       known_alignment = true;
    279  1.1  mrg     }
    280  1.1  mrg   else if (TREE_CODE (exp) == INDIRECT_REF
    281  1.1  mrg 	   || TREE_CODE (exp) == MEM_REF
    282  1.1  mrg 	   || TREE_CODE (exp) == TARGET_MEM_REF)
    283  1.1  mrg     {
    284  1.1  mrg       tree addr = TREE_OPERAND (exp, 0);
    285  1.1  mrg       unsigned ptr_align;
    286  1.1  mrg       unsigned HOST_WIDE_INT ptr_bitpos;
    287  1.1  mrg       unsigned HOST_WIDE_INT ptr_bitmask = ~0;
    288  1.1  mrg 
    289  1.1  mrg       /* If the address is explicitely aligned, handle that.  */
    290  1.1  mrg       if (TREE_CODE (addr) == BIT_AND_EXPR
    291  1.1  mrg 	  && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
    292  1.1  mrg 	{
    293  1.1  mrg 	  ptr_bitmask = TREE_INT_CST_LOW (TREE_OPERAND (addr, 1));
    294  1.1  mrg 	  ptr_bitmask *= BITS_PER_UNIT;
    295  1.1  mrg 	  align = least_bit_hwi (ptr_bitmask);
    296  1.1  mrg 	  addr = TREE_OPERAND (addr, 0);
    297  1.1  mrg 	}
    298  1.1  mrg 
    299  1.1  mrg       known_alignment
    300  1.1  mrg 	= get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
    301  1.1  mrg       align = MAX (ptr_align, align);
    302  1.1  mrg 
    303  1.1  mrg       /* Re-apply explicit alignment to the bitpos.  */
    304  1.1  mrg       ptr_bitpos &= ptr_bitmask;
    305  1.1  mrg 
    306  1.1  mrg       /* The alignment of the pointer operand in a TARGET_MEM_REF
    307  1.1  mrg 	 has to take the variable offset parts into account.  */
    308  1.1  mrg       if (TREE_CODE (exp) == TARGET_MEM_REF)
    309  1.1  mrg 	{
    310  1.1  mrg 	  if (TMR_INDEX (exp))
    311  1.1  mrg 	    {
    312  1.1  mrg 	      unsigned HOST_WIDE_INT step = 1;
    313  1.1  mrg 	      if (TMR_STEP (exp))
    314  1.1  mrg 		step = TREE_INT_CST_LOW (TMR_STEP (exp));
    315  1.1  mrg 	      align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
    316  1.1  mrg 	    }
    317  1.1  mrg 	  if (TMR_INDEX2 (exp))
    318  1.1  mrg 	    align = BITS_PER_UNIT;
    319  1.1  mrg 	  known_alignment = false;
    320  1.1  mrg 	}
    321  1.1  mrg 
    322  1.1  mrg       /* When EXP is an actual memory reference then we can use
    323  1.1  mrg 	 TYPE_ALIGN of a pointer indirection to derive alignment.
    324  1.1  mrg 	 Do so only if get_pointer_alignment_1 did not reveal absolute
    325  1.1  mrg 	 alignment knowledge and if using that alignment would
    326  1.1  mrg 	 improve the situation.  */
    327  1.1  mrg       unsigned int talign;
    328  1.1  mrg       if (!addr_p && !known_alignment
    329  1.1  mrg 	  && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
    330  1.1  mrg 	  && talign > align)
    331  1.1  mrg 	align = talign;
    332  1.1  mrg       else
    333  1.1  mrg 	{
    334  1.1  mrg 	  /* Else adjust bitpos accordingly.  */
    335  1.1  mrg 	  bitpos += ptr_bitpos;
    336  1.1  mrg 	  if (TREE_CODE (exp) == MEM_REF
    337  1.1  mrg 	      || TREE_CODE (exp) == TARGET_MEM_REF)
    338  1.1  mrg 	    bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
    339  1.1  mrg 	}
    340  1.1  mrg     }
    341  1.1  mrg   else if (TREE_CODE (exp) == STRING_CST)
    342  1.1  mrg     {
    343  1.1  mrg       /* STRING_CST are the only constant objects we allow to be not
    344  1.1  mrg          wrapped inside a CONST_DECL.  */
    345  1.1  mrg       align = TYPE_ALIGN (TREE_TYPE (exp));
    346  1.1  mrg       if (CONSTANT_CLASS_P (exp))
    347  1.1  mrg 	align = targetm.constant_alignment (exp, align);
    348  1.1  mrg 
    349  1.1  mrg       known_alignment = true;
    350  1.1  mrg     }
    351  1.1  mrg 
    352  1.1  mrg   /* If there is a non-constant offset part extract the maximum
    353  1.1  mrg      alignment that can prevail.  */
    354  1.1  mrg   if (offset)
    355  1.1  mrg     {
    356  1.1  mrg       unsigned int trailing_zeros = tree_ctz (offset);
    357  1.1  mrg       if (trailing_zeros < HOST_BITS_PER_INT)
    358  1.1  mrg 	{
    359  1.1  mrg 	  unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
    360  1.1  mrg 	  if (inner)
    361  1.1  mrg 	    align = MIN (align, inner);
    362  1.1  mrg 	}
    363  1.1  mrg     }
    364  1.1  mrg 
    365  1.1  mrg   /* Account for the alignment of runtime coefficients, so that the constant
    366  1.1  mrg      bitpos is guaranteed to be accurate.  */
    367  1.1  mrg   unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
    368  1.1  mrg   if (alt_align != 0 && alt_align < align)
    369  1.1  mrg     {
    370  1.1  mrg       align = alt_align;
    371  1.1  mrg       known_alignment = false;
    372  1.1  mrg     }
    373  1.1  mrg 
    374  1.1  mrg   *alignp = align;
    375  1.1  mrg   *bitposp = bitpos.coeffs[0] & (align - 1);
    376  1.1  mrg   return known_alignment;
    377  1.1  mrg }
    378  1.1  mrg 
    379  1.1  mrg /* For a memory reference expression EXP compute values M and N such that M
    380  1.1  mrg    divides (&EXP - N) and such that N < M.  If these numbers can be determined,
    381  1.1  mrg    store M in alignp and N in *BITPOSP and return true.  Otherwise return false
    382  1.1  mrg    and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp.  */
    383  1.1  mrg 
    384  1.1  mrg bool
    385  1.1  mrg get_object_alignment_1 (tree exp, unsigned int *alignp,
    386  1.1  mrg 			unsigned HOST_WIDE_INT *bitposp)
    387  1.1  mrg {
    388  1.1  mrg   /* Strip a WITH_SIZE_EXPR, get_inner_reference doesn't know how to deal
    389  1.1  mrg      with it.  */
    390  1.1  mrg   if (TREE_CODE (exp) == WITH_SIZE_EXPR)
    391  1.1  mrg     exp = TREE_OPERAND (exp, 0);
    392  1.1  mrg   return get_object_alignment_2 (exp, alignp, bitposp, false);
    393  1.1  mrg }
    394  1.1  mrg 
    395  1.1  mrg /* Return the alignment in bits of EXP, an object.  */
    396  1.1  mrg 
    397  1.1  mrg unsigned int
    398  1.1  mrg get_object_alignment (tree exp)
    399  1.1  mrg {
    400  1.1  mrg   unsigned HOST_WIDE_INT bitpos = 0;
    401  1.1  mrg   unsigned int align;
    402  1.1  mrg 
    403  1.1  mrg   get_object_alignment_1 (exp, &align, &bitpos);
    404  1.1  mrg 
    405  1.1  mrg   /* align and bitpos now specify known low bits of the pointer.
    406  1.1  mrg      ptr & (align - 1) == bitpos.  */
    407  1.1  mrg 
    408  1.1  mrg   if (bitpos != 0)
    409  1.1  mrg     align = least_bit_hwi (bitpos);
    410  1.1  mrg   return align;
    411  1.1  mrg }
    412  1.1  mrg 
    413  1.1  mrg /* For a pointer valued expression EXP compute values M and N such that M
    414  1.1  mrg    divides (EXP - N) and such that N < M.  If these numbers can be determined,
    415  1.1  mrg    store M in alignp and N in *BITPOSP and return true.  Return false if
    416  1.1  mrg    the results are just a conservative approximation.
    417  1.1  mrg 
    418  1.1  mrg    If EXP is not a pointer, false is returned too.  */
    419  1.1  mrg 
    420  1.1  mrg bool
    421  1.1  mrg get_pointer_alignment_1 (tree exp, unsigned int *alignp,
    422  1.1  mrg 			 unsigned HOST_WIDE_INT *bitposp)
    423  1.1  mrg {
    424  1.1  mrg   STRIP_NOPS (exp);
    425  1.1  mrg 
    426  1.1  mrg   if (TREE_CODE (exp) == ADDR_EXPR)
    427  1.1  mrg     return get_object_alignment_2 (TREE_OPERAND (exp, 0),
    428  1.1  mrg 				   alignp, bitposp, true);
    429  1.1  mrg   else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
    430  1.1  mrg     {
    431  1.1  mrg       unsigned int align;
    432  1.1  mrg       unsigned HOST_WIDE_INT bitpos;
    433  1.1  mrg       bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
    434  1.1  mrg 					  &align, &bitpos);
    435  1.1  mrg       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
    436  1.1  mrg 	bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
    437  1.1  mrg       else
    438  1.1  mrg 	{
    439  1.1  mrg 	  unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
    440  1.1  mrg 	  if (trailing_zeros < HOST_BITS_PER_INT)
    441  1.1  mrg 	    {
    442  1.1  mrg 	      unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
    443  1.1  mrg 	      if (inner)
    444  1.1  mrg 		align = MIN (align, inner);
    445  1.1  mrg 	    }
    446  1.1  mrg 	}
    447  1.1  mrg       *alignp = align;
    448  1.1  mrg       *bitposp = bitpos & (align - 1);
    449  1.1  mrg       return res;
    450  1.1  mrg     }
    451  1.1  mrg   else if (TREE_CODE (exp) == SSA_NAME
    452  1.1  mrg 	   && POINTER_TYPE_P (TREE_TYPE (exp)))
    453  1.1  mrg     {
    454  1.1  mrg       unsigned int ptr_align, ptr_misalign;
    455  1.1  mrg       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
    456  1.1  mrg 
    457  1.1  mrg       if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
    458  1.1  mrg 	{
    459  1.1  mrg 	  *bitposp = ptr_misalign * BITS_PER_UNIT;
    460  1.1  mrg 	  *alignp = ptr_align * BITS_PER_UNIT;
    461  1.1  mrg 	  /* Make sure to return a sensible alignment when the multiplication
    462  1.1  mrg 	     by BITS_PER_UNIT overflowed.  */
    463  1.1  mrg 	  if (*alignp == 0)
    464  1.1  mrg 	    *alignp = 1u << (HOST_BITS_PER_INT - 1);
    465  1.1  mrg 	  /* We cannot really tell whether this result is an approximation.  */
    466  1.1  mrg 	  return false;
    467  1.1  mrg 	}
    468  1.1  mrg       else
    469  1.1  mrg 	{
    470  1.1  mrg 	  *bitposp = 0;
    471  1.1  mrg 	  *alignp = BITS_PER_UNIT;
    472  1.1  mrg 	  return false;
    473  1.1  mrg 	}
    474  1.1  mrg     }
    475  1.1  mrg   else if (TREE_CODE (exp) == INTEGER_CST)
    476  1.1  mrg     {
    477  1.1  mrg       *alignp = BIGGEST_ALIGNMENT;
    478  1.1  mrg       *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
    479  1.1  mrg 		  & (BIGGEST_ALIGNMENT - 1));
    480  1.1  mrg       return true;
    481  1.1  mrg     }
    482  1.1  mrg 
    483  1.1  mrg   *bitposp = 0;
    484  1.1  mrg   *alignp = BITS_PER_UNIT;
    485  1.1  mrg   return false;
    486  1.1  mrg }
    487  1.1  mrg 
    488  1.1  mrg /* Return the alignment in bits of EXP, a pointer valued expression.
    489  1.1  mrg    The alignment returned is, by default, the alignment of the thing that
    490  1.1  mrg    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
    491  1.1  mrg 
    492  1.1  mrg    Otherwise, look at the expression to see if we can do better, i.e., if the
    493  1.1  mrg    expression is actually pointing at an object whose alignment is tighter.  */
    494  1.1  mrg 
    495  1.1  mrg unsigned int
    496  1.1  mrg get_pointer_alignment (tree exp)
    497  1.1  mrg {
    498  1.1  mrg   unsigned HOST_WIDE_INT bitpos = 0;
    499  1.1  mrg   unsigned int align;
    500  1.1  mrg 
    501  1.1  mrg   get_pointer_alignment_1 (exp, &align, &bitpos);
    502  1.1  mrg 
    503  1.1  mrg   /* align and bitpos now specify known low bits of the pointer.
    504  1.1  mrg      ptr & (align - 1) == bitpos.  */
    505  1.1  mrg 
    506  1.1  mrg   if (bitpos != 0)
    507  1.1  mrg     align = least_bit_hwi (bitpos);
    508  1.1  mrg 
    509  1.1  mrg   return align;
    510  1.1  mrg }
    511  1.1  mrg 
    512  1.1  mrg /* Return the number of leading non-zero elements in the sequence
    513  1.1  mrg    [ PTR, PTR + MAXELTS ) where each element's size is ELTSIZE bytes.
    514  1.1  mrg    ELTSIZE must be a power of 2 less than 8.  Used by c_strlen.  */
    515  1.1  mrg 
    516  1.1  mrg unsigned
    517  1.1  mrg string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
    518  1.1  mrg {
    519  1.1  mrg   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
    520  1.1  mrg 
    521  1.1  mrg   unsigned n;
    522  1.1  mrg 
    523  1.1  mrg   if (eltsize == 1)
    524  1.1  mrg     {
    525  1.1  mrg       /* Optimize the common case of plain char.  */
    526  1.1  mrg       for (n = 0; n < maxelts; n++)
    527  1.1  mrg 	{
    528  1.1  mrg 	  const char *elt = (const char*) ptr + n;
    529  1.1  mrg 	  if (!*elt)
    530  1.1  mrg 	    break;
    531  1.1  mrg 	}
    532  1.1  mrg     }
    533  1.1  mrg   else
    534  1.1  mrg     {
    535  1.1  mrg       for (n = 0; n < maxelts; n++)
    536  1.1  mrg 	{
    537  1.1  mrg 	  const char *elt = (const char*) ptr + n * eltsize;
    538  1.1  mrg 	  if (!memcmp (elt, "\0\0\0\0", eltsize))
    539  1.1  mrg 	    break;
    540  1.1  mrg 	}
    541  1.1  mrg     }
    542  1.1  mrg   return n;
    543  1.1  mrg }
    544  1.1  mrg 
    545  1.1  mrg /* Compute the length of a null-terminated character string or wide
    546  1.1  mrg    character string handling character sizes of 1, 2, and 4 bytes.
    547  1.1  mrg    TREE_STRING_LENGTH is not the right way because it evaluates to
    548  1.1  mrg    the size of the character array in bytes (as opposed to characters)
    549  1.1  mrg    and because it can contain a zero byte in the middle.
    550  1.1  mrg 
    551  1.1  mrg    ONLY_VALUE should be nonzero if the result is not going to be emitted
    552  1.1  mrg    into the instruction stream and zero if it is going to be expanded.
    553  1.1  mrg    E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
    554  1.1  mrg    is returned, otherwise NULL, since
    555  1.1  mrg    len = c_strlen (ARG, 1); if (len) expand_expr (len, ...); would not
    556  1.1  mrg    evaluate the side-effects.
    557  1.1  mrg 
    558  1.1  mrg    If ONLY_VALUE is two then we do not emit warnings about out-of-bound
    559  1.1  mrg    accesses.  Note that this implies the result is not going to be emitted
    560  1.1  mrg    into the instruction stream.
    561  1.1  mrg 
    562  1.1  mrg    Additional information about the string accessed may be recorded
    563  1.1  mrg    in DATA.  For example, if ARG references an unterminated string,
    564  1.1  mrg    then the declaration will be stored in the DECL field.   If the
    565  1.1  mrg    length of the unterminated string can be determined, it'll be
    566  1.1  mrg    stored in the LEN field.  Note this length could well be different
    567  1.1  mrg    than what a C strlen call would return.
    568  1.1  mrg 
    569  1.1  mrg    ELTSIZE is 1 for normal single byte character strings, and 2 or
    570  1.1  mrg    4 for wide characer strings.  ELTSIZE is by default 1.
    571  1.1  mrg 
    572  1.1  mrg    The value returned is of type `ssizetype'.  */
    573  1.1  mrg 
    574  1.1  mrg tree
    575  1.1  mrg c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
    576  1.1  mrg {
    577  1.1  mrg   /* If we were not passed a DATA pointer, then get one to a local
    578  1.1  mrg      structure.  That avoids having to check DATA for NULL before
    579  1.1  mrg      each time we want to use it.  */
    580  1.1  mrg   c_strlen_data local_strlen_data = { };
    581  1.1  mrg   if (!data)
    582  1.1  mrg     data = &local_strlen_data;
    583  1.1  mrg 
    584  1.1  mrg   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
    585  1.1  mrg 
    586  1.1  mrg   tree src = STRIP_NOPS (arg);
    587  1.1  mrg   if (TREE_CODE (src) == COND_EXPR
    588  1.1  mrg       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
    589  1.1  mrg     {
    590  1.1  mrg       tree len1, len2;
    591  1.1  mrg 
    592  1.1  mrg       len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
    593  1.1  mrg       len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
    594  1.1  mrg       if (tree_int_cst_equal (len1, len2))
    595  1.1  mrg 	return len1;
    596  1.1  mrg     }
    597  1.1  mrg 
    598  1.1  mrg   if (TREE_CODE (src) == COMPOUND_EXPR
    599  1.1  mrg       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
    600  1.1  mrg     return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
    601  1.1  mrg 
    602  1.1  mrg   location_t loc = EXPR_LOC_OR_LOC (src, input_location);
    603  1.1  mrg 
    604  1.1  mrg   /* Offset from the beginning of the string in bytes.  */
    605  1.1  mrg   tree byteoff;
    606  1.1  mrg   tree memsize;
    607  1.1  mrg   tree decl;
    608  1.1  mrg   src = string_constant (src, &byteoff, &memsize, &decl);
    609  1.1  mrg   if (src == 0)
    610  1.1  mrg     return NULL_TREE;
    611  1.1  mrg 
    612  1.1  mrg   /* Determine the size of the string element.  */
    613  1.1  mrg   if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
    614  1.1  mrg     return NULL_TREE;
    615  1.1  mrg 
    616  1.1  mrg   /* Set MAXELTS to sizeof (SRC) / sizeof (*SRC) - 1, the maximum possible
    617  1.1  mrg      length of SRC.  Prefer TYPE_SIZE() to TREE_STRING_LENGTH() if possible
    618  1.1  mrg      in case the latter is less than the size of the array, such as when
    619  1.1  mrg      SRC refers to a short string literal used to initialize a large array.
    620  1.1  mrg      In that case, the elements of the array after the terminating NUL are
    621  1.1  mrg      all NUL.  */
    622  1.1  mrg   HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
    623  1.1  mrg   strelts = strelts / eltsize;
    624  1.1  mrg 
    625  1.1  mrg   if (!tree_fits_uhwi_p (memsize))
    626  1.1  mrg     return NULL_TREE;
    627  1.1  mrg 
    628  1.1  mrg   HOST_WIDE_INT maxelts = tree_to_uhwi (memsize) / eltsize;
    629  1.1  mrg 
    630  1.1  mrg   /* PTR can point to the byte representation of any string type, including
    631  1.1  mrg      char* and wchar_t*.  */
    632  1.1  mrg   const char *ptr = TREE_STRING_POINTER (src);
    633  1.1  mrg 
    634  1.1  mrg   if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
    635  1.1  mrg     {
    636  1.1  mrg       /* The code below works only for single byte character types.  */
    637  1.1  mrg       if (eltsize != 1)
    638  1.1  mrg 	return NULL_TREE;
    639  1.1  mrg 
    640  1.1  mrg       /* If the string has an internal NUL character followed by any
    641  1.1  mrg 	 non-NUL characters (e.g., "foo\0bar"), we can't compute
    642  1.1  mrg 	 the offset to the following NUL if we don't know where to
    643  1.1  mrg 	 start searching for it.  */
    644  1.1  mrg       unsigned len = string_length (ptr, eltsize, strelts);
    645  1.1  mrg 
    646  1.1  mrg       /* Return when an embedded null character is found or none at all.
    647  1.1  mrg 	 In the latter case, set the DECL/LEN field in the DATA structure
    648  1.1  mrg 	 so that callers may examine them.  */
    649  1.1  mrg       if (len + 1 < strelts)
    650  1.1  mrg 	return NULL_TREE;
    651  1.1  mrg       else if (len >= maxelts)
    652  1.1  mrg 	{
    653  1.1  mrg 	  data->decl = decl;
    654  1.1  mrg 	  data->off = byteoff;
    655  1.1  mrg 	  data->minlen = ssize_int (len);
    656  1.1  mrg 	  return NULL_TREE;
    657  1.1  mrg 	}
    658  1.1  mrg 
    659  1.1  mrg       /* For empty strings the result should be zero.  */
    660  1.1  mrg       if (len == 0)
    661  1.1  mrg 	return ssize_int (0);
    662  1.1  mrg 
    663  1.1  mrg       /* We don't know the starting offset, but we do know that the string
    664  1.1  mrg 	 has no internal zero bytes.  If the offset falls within the bounds
    665  1.1  mrg 	 of the string subtract the offset from the length of the string,
    666  1.1  mrg 	 and return that.  Otherwise the length is zero.  Take care to
    667  1.1  mrg 	 use SAVE_EXPR in case the OFFSET has side-effects.  */
    668  1.1  mrg       tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
    669  1.1  mrg 						 : byteoff;
    670  1.1  mrg       offsave = fold_convert_loc (loc, sizetype, offsave);
    671  1.1  mrg       tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
    672  1.1  mrg 				      size_int (len));
    673  1.1  mrg       tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
    674  1.1  mrg 				     offsave);
    675  1.1  mrg       lenexp = fold_convert_loc (loc, ssizetype, lenexp);
    676  1.1  mrg       return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
    677  1.1  mrg 			      build_zero_cst (ssizetype));
    678  1.1  mrg     }
    679  1.1  mrg 
    680  1.1  mrg   /* Offset from the beginning of the string in elements.  */
    681  1.1  mrg   HOST_WIDE_INT eltoff;
    682  1.1  mrg 
    683  1.1  mrg   /* We have a known offset into the string.  Start searching there for
    684  1.1  mrg      a null character if we can represent it as a single HOST_WIDE_INT.  */
    685  1.1  mrg   if (byteoff == 0)
    686  1.1  mrg     eltoff = 0;
    687  1.1  mrg   else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
    688  1.1  mrg     eltoff = -1;
    689  1.1  mrg   else
    690  1.1  mrg     eltoff = tree_to_uhwi (byteoff) / eltsize;
    691  1.1  mrg 
    692  1.1  mrg   /* If the offset is known to be out of bounds, warn, and call strlen at
    693  1.1  mrg      runtime.  */
    694  1.1  mrg   if (eltoff < 0 || eltoff >= maxelts)
    695  1.1  mrg     {
    696  1.1  mrg       /* Suppress multiple warnings for propagated constant strings.  */
    697  1.1  mrg       if (only_value != 2
    698  1.1  mrg 	  && !warning_suppressed_p (arg, OPT_Warray_bounds)
    699  1.1  mrg 	  && warning_at (loc, OPT_Warray_bounds,
    700  1.1  mrg 			 "offset %qwi outside bounds of constant string",
    701  1.1  mrg 			 eltoff))
    702  1.1  mrg 	{
    703  1.1  mrg 	  if (decl)
    704  1.1  mrg 	    inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
    705  1.1  mrg 	  suppress_warning (arg, OPT_Warray_bounds);
    706  1.1  mrg 	}
    707  1.1  mrg       return NULL_TREE;
    708  1.1  mrg     }
    709  1.1  mrg 
    710  1.1  mrg   /* If eltoff is larger than strelts but less than maxelts the
    711  1.1  mrg      string length is zero, since the excess memory will be zero.  */
    712  1.1  mrg   if (eltoff > strelts)
    713  1.1  mrg     return ssize_int (0);
    714  1.1  mrg 
    715  1.1  mrg   /* Use strlen to search for the first zero byte.  Since any strings
    716  1.1  mrg      constructed with build_string will have nulls appended, we win even
    717  1.1  mrg      if we get handed something like (char[4])"abcd".
    718  1.1  mrg 
    719  1.1  mrg      Since ELTOFF is our starting index into the string, no further
    720  1.1  mrg      calculation is needed.  */
    721  1.1  mrg   unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
    722  1.1  mrg 				strelts - eltoff);
    723  1.1  mrg 
    724  1.1  mrg   /* Don't know what to return if there was no zero termination.
    725  1.1  mrg      Ideally this would turn into a gcc_checking_assert over time.
    726  1.1  mrg      Set DECL/LEN so callers can examine them.  */
    727  1.1  mrg   if (len >= maxelts - eltoff)
    728  1.1  mrg     {
    729  1.1  mrg       data->decl = decl;
    730  1.1  mrg       data->off = byteoff;
    731  1.1  mrg       data->minlen = ssize_int (len);
    732  1.1  mrg       return NULL_TREE;
    733  1.1  mrg     }
    734  1.1  mrg 
    735  1.1  mrg   return ssize_int (len);
    736  1.1  mrg }
    737  1.1  mrg 
    738  1.1  mrg /* Return a constant integer corresponding to target reading
    739  1.1  mrg    GET_MODE_BITSIZE (MODE) bits from string constant STR.  If
    740  1.1  mrg    NULL_TERMINATED_P, reading stops after '\0' character, all further ones
    741  1.1  mrg    are assumed to be zero, otherwise it reads as many characters
    742  1.1  mrg    as needed.  */
    743  1.1  mrg 
    744  1.1  mrg rtx
    745  1.1  mrg c_readstr (const char *str, scalar_int_mode mode,
    746  1.1  mrg 	   bool null_terminated_p/*=true*/)
    747  1.1  mrg {
    748  1.1  mrg   HOST_WIDE_INT ch;
    749  1.1  mrg   unsigned int i, j;
    750  1.1  mrg   HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
    751  1.1  mrg 
    752  1.1  mrg   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
    753  1.1  mrg   unsigned int len = (GET_MODE_PRECISION (mode) + HOST_BITS_PER_WIDE_INT - 1)
    754  1.1  mrg     / HOST_BITS_PER_WIDE_INT;
    755  1.1  mrg 
    756  1.1  mrg   gcc_assert (len <= MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT);
    757  1.1  mrg   for (i = 0; i < len; i++)
    758  1.1  mrg     tmp[i] = 0;
    759  1.1  mrg 
    760  1.1  mrg   ch = 1;
    761  1.1  mrg   for (i = 0; i < GET_MODE_SIZE (mode); i++)
    762  1.1  mrg     {
    763  1.1  mrg       j = i;
    764  1.1  mrg       if (WORDS_BIG_ENDIAN)
    765  1.1  mrg 	j = GET_MODE_SIZE (mode) - i - 1;
    766  1.1  mrg       if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
    767  1.1  mrg 	  && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
    768  1.1  mrg 	j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
    769  1.1  mrg       j *= BITS_PER_UNIT;
    770  1.1  mrg 
    771  1.1  mrg       if (ch || !null_terminated_p)
    772  1.1  mrg 	ch = (unsigned char) str[i];
    773  1.1  mrg       tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
    774  1.1  mrg     }
    775  1.1  mrg 
    776  1.1  mrg   wide_int c = wide_int::from_array (tmp, len, GET_MODE_PRECISION (mode));
    777  1.1  mrg   return immed_wide_int_const (c, mode);
    778  1.1  mrg }
    779  1.1  mrg 
    780  1.1  mrg /* Cast a target constant CST to target CHAR and if that value fits into
    781  1.1  mrg    host char type, return zero and put that value into variable pointed to by
    782  1.1  mrg    P.  */
    783  1.1  mrg 
    784  1.1  mrg static int
    785  1.1  mrg target_char_cast (tree cst, char *p)
    786  1.1  mrg {
    787  1.1  mrg   unsigned HOST_WIDE_INT val, hostval;
    788  1.1  mrg 
    789  1.1  mrg   if (TREE_CODE (cst) != INTEGER_CST
    790  1.1  mrg       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
    791  1.1  mrg     return 1;
    792  1.1  mrg 
    793  1.1  mrg   /* Do not care if it fits or not right here.  */
    794  1.1  mrg   val = TREE_INT_CST_LOW (cst);
    795  1.1  mrg 
    796  1.1  mrg   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
    797  1.1  mrg     val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
    798  1.1  mrg 
    799  1.1  mrg   hostval = val;
    800  1.1  mrg   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
    801  1.1  mrg     hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
    802  1.1  mrg 
    803  1.1  mrg   if (val != hostval)
    804  1.1  mrg     return 1;
    805  1.1  mrg 
    806  1.1  mrg   *p = hostval;
    807  1.1  mrg   return 0;
    808  1.1  mrg }
    809  1.1  mrg 
    810  1.1  mrg /* Similar to save_expr, but assumes that arbitrary code is not executed
    811  1.1  mrg    in between the multiple evaluations.  In particular, we assume that a
    812  1.1  mrg    non-addressable local variable will not be modified.  */
    813  1.1  mrg 
    814  1.1  mrg static tree
    815  1.1  mrg builtin_save_expr (tree exp)
    816  1.1  mrg {
    817  1.1  mrg   if (TREE_CODE (exp) == SSA_NAME
    818  1.1  mrg       || (TREE_ADDRESSABLE (exp) == 0
    819  1.1  mrg 	  && (TREE_CODE (exp) == PARM_DECL
    820  1.1  mrg 	      || (VAR_P (exp) && !TREE_STATIC (exp)))))
    821  1.1  mrg     return exp;
    822  1.1  mrg 
    823  1.1  mrg   return save_expr (exp);
    824  1.1  mrg }
    825  1.1  mrg 
    826  1.1  mrg /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
    827  1.1  mrg    times to get the address of either a higher stack frame, or a return
    828  1.1  mrg    address located within it (depending on FNDECL_CODE).  */
    829  1.1  mrg 
    830  1.1  mrg static rtx
    831  1.1  mrg expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
    832  1.1  mrg {
    833  1.1  mrg   int i;
    834  1.1  mrg   rtx tem = INITIAL_FRAME_ADDRESS_RTX;
    835  1.1  mrg   if (tem == NULL_RTX)
    836  1.1  mrg     {
    837  1.1  mrg       /* For a zero count with __builtin_return_address, we don't care what
    838  1.1  mrg 	 frame address we return, because target-specific definitions will
    839  1.1  mrg 	 override us.  Therefore frame pointer elimination is OK, and using
    840  1.1  mrg 	 the soft frame pointer is OK.
    841  1.1  mrg 
    842  1.1  mrg 	 For a nonzero count, or a zero count with __builtin_frame_address,
    843  1.1  mrg 	 we require a stable offset from the current frame pointer to the
    844  1.1  mrg 	 previous one, so we must use the hard frame pointer, and
    845  1.1  mrg 	 we must disable frame pointer elimination.  */
    846  1.1  mrg       if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
    847  1.1  mrg 	tem = frame_pointer_rtx;
    848  1.1  mrg       else
    849  1.1  mrg 	{
    850  1.1  mrg 	  tem = hard_frame_pointer_rtx;
    851  1.1  mrg 
    852  1.1  mrg 	  /* Tell reload not to eliminate the frame pointer.  */
    853  1.1  mrg 	  crtl->accesses_prior_frames = 1;
    854  1.1  mrg 	}
    855  1.1  mrg     }
    856  1.1  mrg 
    857  1.1  mrg   if (count > 0)
    858  1.1  mrg     SETUP_FRAME_ADDRESSES ();
    859  1.1  mrg 
    860  1.1  mrg   /* On the SPARC, the return address is not in the frame, it is in a
    861  1.1  mrg      register.  There is no way to access it off of the current frame
    862  1.1  mrg      pointer, but it can be accessed off the previous frame pointer by
    863  1.1  mrg      reading the value from the register window save area.  */
    864  1.1  mrg   if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
    865  1.1  mrg     count--;
    866  1.1  mrg 
    867  1.1  mrg   /* Scan back COUNT frames to the specified frame.  */
    868  1.1  mrg   for (i = 0; i < count; i++)
    869  1.1  mrg     {
    870  1.1  mrg       /* Assume the dynamic chain pointer is in the word that the
    871  1.1  mrg 	 frame address points to, unless otherwise specified.  */
    872  1.1  mrg       tem = DYNAMIC_CHAIN_ADDRESS (tem);
    873  1.1  mrg       tem = memory_address (Pmode, tem);
    874  1.1  mrg       tem = gen_frame_mem (Pmode, tem);
    875  1.1  mrg       tem = copy_to_reg (tem);
    876  1.1  mrg     }
    877  1.1  mrg 
    878  1.1  mrg   /* For __builtin_frame_address, return what we've got.  But, on
    879  1.1  mrg      the SPARC for example, we may have to add a bias.  */
    880  1.1  mrg   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
    881  1.1  mrg     return FRAME_ADDR_RTX (tem);
    882  1.1  mrg 
    883  1.1  mrg   /* For __builtin_return_address, get the return address from that frame.  */
    884  1.1  mrg #ifdef RETURN_ADDR_RTX
    885  1.1  mrg   tem = RETURN_ADDR_RTX (count, tem);
    886  1.1  mrg #else
    887  1.1  mrg   tem = memory_address (Pmode,
    888  1.1  mrg 			plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
    889  1.1  mrg   tem = gen_frame_mem (Pmode, tem);
    890  1.1  mrg #endif
    891  1.1  mrg   return tem;
    892  1.1  mrg }
    893  1.1  mrg 
    894  1.1  mrg /* Alias set used for setjmp buffer.  */
    895  1.1  mrg static alias_set_type setjmp_alias_set = -1;
    896  1.1  mrg 
    897  1.1  mrg /* Construct the leading half of a __builtin_setjmp call.  Control will
    898  1.1  mrg    return to RECEIVER_LABEL.  This is also called directly by the SJLJ
    899  1.1  mrg    exception handling code.  */
    900  1.1  mrg 
    901  1.1  mrg void
    902  1.1  mrg expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
    903  1.1  mrg {
    904  1.1  mrg   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
    905  1.1  mrg   rtx stack_save;
    906  1.1  mrg   rtx mem;
    907  1.1  mrg 
    908  1.1  mrg   if (setjmp_alias_set == -1)
    909  1.1  mrg     setjmp_alias_set = new_alias_set ();
    910  1.1  mrg 
    911  1.1  mrg   buf_addr = convert_memory_address (Pmode, buf_addr);
    912  1.1  mrg 
    913  1.1  mrg   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
    914  1.1  mrg 
    915  1.1  mrg   /* We store the frame pointer and the address of receiver_label in
    916  1.1  mrg      the buffer and use the rest of it for the stack save area, which
    917  1.1  mrg      is machine-dependent.  */
    918  1.1  mrg 
    919  1.1  mrg   mem = gen_rtx_MEM (Pmode, buf_addr);
    920  1.1  mrg   set_mem_alias_set (mem, setjmp_alias_set);
    921  1.1  mrg   emit_move_insn (mem, hard_frame_pointer_rtx);
    922  1.1  mrg 
    923  1.1  mrg   mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
    924  1.1  mrg 					   GET_MODE_SIZE (Pmode))),
    925  1.1  mrg   set_mem_alias_set (mem, setjmp_alias_set);
    926  1.1  mrg 
    927  1.1  mrg   emit_move_insn (validize_mem (mem),
    928  1.1  mrg 		  force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
    929  1.1  mrg 
    930  1.1  mrg   stack_save = gen_rtx_MEM (sa_mode,
    931  1.1  mrg 			    plus_constant (Pmode, buf_addr,
    932  1.1  mrg 					   2 * GET_MODE_SIZE (Pmode)));
    933  1.1  mrg   set_mem_alias_set (stack_save, setjmp_alias_set);
    934  1.1  mrg   emit_stack_save (SAVE_NONLOCAL, &stack_save);
    935  1.1  mrg 
    936  1.1  mrg   /* If there is further processing to do, do it.  */
    937  1.1  mrg   if (targetm.have_builtin_setjmp_setup ())
    938  1.1  mrg     emit_insn (targetm.gen_builtin_setjmp_setup (buf_addr));
    939  1.1  mrg 
    940  1.1  mrg   /* We have a nonlocal label.   */
    941  1.1  mrg   cfun->has_nonlocal_label = 1;
    942  1.1  mrg }
    943  1.1  mrg 
    944  1.1  mrg /* Construct the trailing part of a __builtin_setjmp call.  This is
    945  1.1  mrg    also called directly by the SJLJ exception handling code.
    946  1.1  mrg    If RECEIVER_LABEL is NULL, instead contruct a nonlocal goto handler.  */
    947  1.1  mrg 
    948  1.1  mrg void
    949  1.1  mrg expand_builtin_setjmp_receiver (rtx receiver_label)
    950  1.1  mrg {
    951  1.1  mrg   rtx chain;
    952  1.1  mrg 
    953  1.1  mrg   /* Mark the FP as used when we get here, so we have to make sure it's
    954  1.1  mrg      marked as used by this function.  */
    955  1.1  mrg   emit_use (hard_frame_pointer_rtx);
    956  1.1  mrg 
    957  1.1  mrg   /* Mark the static chain as clobbered here so life information
    958  1.1  mrg      doesn't get messed up for it.  */
    959  1.1  mrg   chain = rtx_for_static_chain (current_function_decl, true);
    960  1.1  mrg   if (chain && REG_P (chain))
    961  1.1  mrg     emit_clobber (chain);
    962  1.1  mrg 
    963  1.1  mrg   if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
    964  1.1  mrg     {
    965  1.1  mrg       /* If the argument pointer can be eliminated in favor of the
    966  1.1  mrg 	 frame pointer, we don't need to restore it.  We assume here
    967  1.1  mrg 	 that if such an elimination is present, it can always be used.
    968  1.1  mrg 	 This is the case on all known machines; if we don't make this
    969  1.1  mrg 	 assumption, we do unnecessary saving on many machines.  */
    970  1.1  mrg       size_t i;
    971  1.1  mrg       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
    972  1.1  mrg 
    973  1.1  mrg       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
    974  1.1  mrg 	if (elim_regs[i].from == ARG_POINTER_REGNUM
    975  1.1  mrg 	    && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
    976  1.1  mrg 	  break;
    977  1.1  mrg 
    978  1.1  mrg       if (i == ARRAY_SIZE (elim_regs))
    979  1.1  mrg 	{
    980  1.1  mrg 	  /* Now restore our arg pointer from the address at which it
    981  1.1  mrg 	     was saved in our stack frame.  */
    982  1.1  mrg 	  emit_move_insn (crtl->args.internal_arg_pointer,
    983  1.1  mrg 			  copy_to_reg (get_arg_pointer_save_area ()));
    984  1.1  mrg 	}
    985  1.1  mrg     }
    986  1.1  mrg 
    987  1.1  mrg   if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
    988  1.1  mrg     emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
    989  1.1  mrg   else if (targetm.have_nonlocal_goto_receiver ())
    990  1.1  mrg     emit_insn (targetm.gen_nonlocal_goto_receiver ());
    991  1.1  mrg   else
    992  1.1  mrg     { /* Nothing */ }
    993  1.1  mrg 
    994  1.1  mrg   /* We must not allow the code we just generated to be reordered by
    995  1.1  mrg      scheduling.  Specifically, the update of the frame pointer must
    996  1.1  mrg      happen immediately, not later.  */
    997  1.1  mrg   emit_insn (gen_blockage ());
    998  1.1  mrg }
    999  1.1  mrg 
   1000  1.1  mrg /* __builtin_longjmp is passed a pointer to an array of five words (not
   1001  1.1  mrg    all will be used on all machines).  It operates similarly to the C
   1002  1.1  mrg    library function of the same name, but is more efficient.  Much of
   1003  1.1  mrg    the code below is copied from the handling of non-local gotos.  */
   1004  1.1  mrg 
   1005  1.1  mrg static void
   1006  1.1  mrg expand_builtin_longjmp (rtx buf_addr, rtx value)
   1007  1.1  mrg {
   1008  1.1  mrg   rtx fp, lab, stack;
   1009  1.1  mrg   rtx_insn *insn, *last;
   1010  1.1  mrg   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
   1011  1.1  mrg 
   1012  1.1  mrg   /* DRAP is needed for stack realign if longjmp is expanded to current
   1013  1.1  mrg      function  */
   1014  1.1  mrg   if (SUPPORTS_STACK_ALIGNMENT)
   1015  1.1  mrg     crtl->need_drap = true;
   1016  1.1  mrg 
   1017  1.1  mrg   if (setjmp_alias_set == -1)
   1018  1.1  mrg     setjmp_alias_set = new_alias_set ();
   1019  1.1  mrg 
   1020  1.1  mrg   buf_addr = convert_memory_address (Pmode, buf_addr);
   1021  1.1  mrg 
   1022  1.1  mrg   buf_addr = force_reg (Pmode, buf_addr);
   1023  1.1  mrg 
   1024  1.1  mrg   /* We require that the user must pass a second argument of 1, because
   1025  1.1  mrg      that is what builtin_setjmp will return.  */
   1026  1.1  mrg   gcc_assert (value == const1_rtx);
   1027  1.1  mrg 
   1028  1.1  mrg   last = get_last_insn ();
   1029  1.1  mrg   if (targetm.have_builtin_longjmp ())
   1030  1.1  mrg     emit_insn (targetm.gen_builtin_longjmp (buf_addr));
   1031  1.1  mrg   else
   1032  1.1  mrg     {
   1033  1.1  mrg       fp = gen_rtx_MEM (Pmode, buf_addr);
   1034  1.1  mrg       lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
   1035  1.1  mrg 					       GET_MODE_SIZE (Pmode)));
   1036  1.1  mrg 
   1037  1.1  mrg       stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
   1038  1.1  mrg 						   2 * GET_MODE_SIZE (Pmode)));
   1039  1.1  mrg       set_mem_alias_set (fp, setjmp_alias_set);
   1040  1.1  mrg       set_mem_alias_set (lab, setjmp_alias_set);
   1041  1.1  mrg       set_mem_alias_set (stack, setjmp_alias_set);
   1042  1.1  mrg 
   1043  1.1  mrg       /* Pick up FP, label, and SP from the block and jump.  This code is
   1044  1.1  mrg 	 from expand_goto in stmt.cc; see there for detailed comments.  */
   1045  1.1  mrg       if (targetm.have_nonlocal_goto ())
   1046  1.1  mrg 	/* We have to pass a value to the nonlocal_goto pattern that will
   1047  1.1  mrg 	   get copied into the static_chain pointer, but it does not matter
   1048  1.1  mrg 	   what that value is, because builtin_setjmp does not use it.  */
   1049  1.1  mrg 	emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
   1050  1.1  mrg       else
   1051  1.1  mrg 	{
   1052  1.1  mrg 	  emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
   1053  1.1  mrg 	  emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
   1054  1.1  mrg 
   1055  1.1  mrg 	  lab = copy_to_reg (lab);
   1056  1.1  mrg 
   1057  1.1  mrg 	  /* Restore the frame pointer and stack pointer.  We must use a
   1058  1.1  mrg 	     temporary since the setjmp buffer may be a local.  */
   1059  1.1  mrg 	  fp = copy_to_reg (fp);
   1060  1.1  mrg 	  emit_stack_restore (SAVE_NONLOCAL, stack);
   1061  1.1  mrg 
   1062  1.1  mrg 	  /* Ensure the frame pointer move is not optimized.  */
   1063  1.1  mrg 	  emit_insn (gen_blockage ());
   1064  1.1  mrg 	  emit_clobber (hard_frame_pointer_rtx);
   1065  1.1  mrg 	  emit_clobber (frame_pointer_rtx);
   1066  1.1  mrg 	  emit_move_insn (hard_frame_pointer_rtx, fp);
   1067  1.1  mrg 
   1068  1.1  mrg 	  emit_use (hard_frame_pointer_rtx);
   1069  1.1  mrg 	  emit_use (stack_pointer_rtx);
   1070  1.1  mrg 	  emit_indirect_jump (lab);
   1071  1.1  mrg 	}
   1072  1.1  mrg     }
   1073  1.1  mrg 
   1074  1.1  mrg   /* Search backwards and mark the jump insn as a non-local goto.
   1075  1.1  mrg      Note that this precludes the use of __builtin_longjmp to a
   1076  1.1  mrg      __builtin_setjmp target in the same function.  However, we've
   1077  1.1  mrg      already cautioned the user that these functions are for
   1078  1.1  mrg      internal exception handling use only.  */
   1079  1.1  mrg   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
   1080  1.1  mrg     {
   1081  1.1  mrg       gcc_assert (insn != last);
   1082  1.1  mrg 
   1083  1.1  mrg       if (JUMP_P (insn))
   1084  1.1  mrg 	{
   1085  1.1  mrg 	  add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
   1086  1.1  mrg 	  break;
   1087  1.1  mrg 	}
   1088  1.1  mrg       else if (CALL_P (insn))
   1089  1.1  mrg 	break;
   1090  1.1  mrg     }
   1091  1.1  mrg }
   1092  1.1  mrg 
   1093  1.1  mrg static inline bool
   1094  1.1  mrg more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
   1095  1.1  mrg {
   1096  1.1  mrg   return (iter->i < iter->n);
   1097  1.1  mrg }
   1098  1.1  mrg 
   1099  1.1  mrg /* This function validates the types of a function call argument list
   1100  1.1  mrg    against a specified list of tree_codes.  If the last specifier is a 0,
   1101  1.1  mrg    that represents an ellipsis, otherwise the last specifier must be a
   1102  1.1  mrg    VOID_TYPE.  */
   1103  1.1  mrg 
   1104  1.1  mrg static bool
   1105  1.1  mrg validate_arglist (const_tree callexpr, ...)
   1106  1.1  mrg {
   1107  1.1  mrg   enum tree_code code;
   1108  1.1  mrg   bool res = 0;
   1109  1.1  mrg   va_list ap;
   1110  1.1  mrg   const_call_expr_arg_iterator iter;
   1111  1.1  mrg   const_tree arg;
   1112  1.1  mrg 
   1113  1.1  mrg   va_start (ap, callexpr);
   1114  1.1  mrg   init_const_call_expr_arg_iterator (callexpr, &iter);
   1115  1.1  mrg 
   1116  1.1  mrg   /* Get a bitmap of pointer argument numbers declared attribute nonnull.  */
   1117  1.1  mrg   tree fn = CALL_EXPR_FN (callexpr);
   1118  1.1  mrg   bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
   1119  1.1  mrg 
   1120  1.1  mrg   for (unsigned argno = 1; ; ++argno)
   1121  1.1  mrg     {
   1122  1.1  mrg       code = (enum tree_code) va_arg (ap, int);
   1123  1.1  mrg 
   1124  1.1  mrg       switch (code)
   1125  1.1  mrg 	{
   1126  1.1  mrg 	case 0:
   1127  1.1  mrg 	  /* This signifies an ellipses, any further arguments are all ok.  */
   1128  1.1  mrg 	  res = true;
   1129  1.1  mrg 	  goto end;
   1130  1.1  mrg 	case VOID_TYPE:
   1131  1.1  mrg 	  /* This signifies an endlink, if no arguments remain, return
   1132  1.1  mrg 	     true, otherwise return false.  */
   1133  1.1  mrg 	  res = !more_const_call_expr_args_p (&iter);
   1134  1.1  mrg 	  goto end;
   1135  1.1  mrg 	case POINTER_TYPE:
   1136  1.1  mrg 	  /* The actual argument must be nonnull when either the whole
   1137  1.1  mrg 	     called function has been declared nonnull, or when the formal
   1138  1.1  mrg 	     argument corresponding to the actual argument has been.  */
   1139  1.1  mrg 	  if (argmap
   1140  1.1  mrg 	      && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
   1141  1.1  mrg 	    {
   1142  1.1  mrg 	      arg = next_const_call_expr_arg (&iter);
   1143  1.1  mrg 	      if (!validate_arg (arg, code) || integer_zerop (arg))
   1144  1.1  mrg 		goto end;
   1145  1.1  mrg 	      break;
   1146  1.1  mrg 	    }
   1147  1.1  mrg 	  /* FALLTHRU */
   1148  1.1  mrg 	default:
   1149  1.1  mrg 	  /* If no parameters remain or the parameter's code does not
   1150  1.1  mrg 	     match the specified code, return false.  Otherwise continue
   1151  1.1  mrg 	     checking any remaining arguments.  */
   1152  1.1  mrg 	  arg = next_const_call_expr_arg (&iter);
   1153  1.1  mrg 	  if (!validate_arg (arg, code))
   1154  1.1  mrg 	    goto end;
   1155  1.1  mrg 	  break;
   1156  1.1  mrg 	}
   1157  1.1  mrg     }
   1158  1.1  mrg 
   1159  1.1  mrg   /* We need gotos here since we can only have one VA_CLOSE in a
   1160  1.1  mrg      function.  */
   1161  1.1  mrg  end: ;
   1162  1.1  mrg   va_end (ap);
   1163  1.1  mrg 
   1164  1.1  mrg   BITMAP_FREE (argmap);
   1165  1.1  mrg 
   1166  1.1  mrg   return res;
   1167  1.1  mrg }
   1168  1.1  mrg 
   1169  1.1  mrg /* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
   1170  1.1  mrg    and the address of the save area.  */
   1171  1.1  mrg 
   1172  1.1  mrg static rtx
   1173  1.1  mrg expand_builtin_nonlocal_goto (tree exp)
   1174  1.1  mrg {
   1175  1.1  mrg   tree t_label, t_save_area;
   1176  1.1  mrg   rtx r_label, r_save_area, r_fp, r_sp;
   1177  1.1  mrg   rtx_insn *insn;
   1178  1.1  mrg 
   1179  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   1180  1.1  mrg     return NULL_RTX;
   1181  1.1  mrg 
   1182  1.1  mrg   t_label = CALL_EXPR_ARG (exp, 0);
   1183  1.1  mrg   t_save_area = CALL_EXPR_ARG (exp, 1);
   1184  1.1  mrg 
   1185  1.1  mrg   r_label = expand_normal (t_label);
   1186  1.1  mrg   r_label = convert_memory_address (Pmode, r_label);
   1187  1.1  mrg   r_save_area = expand_normal (t_save_area);
   1188  1.1  mrg   r_save_area = convert_memory_address (Pmode, r_save_area);
   1189  1.1  mrg   /* Copy the address of the save location to a register just in case it was
   1190  1.1  mrg      based on the frame pointer.   */
   1191  1.1  mrg   r_save_area = copy_to_reg (r_save_area);
   1192  1.1  mrg   r_fp = gen_rtx_MEM (Pmode, r_save_area);
   1193  1.1  mrg   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
   1194  1.1  mrg 		      plus_constant (Pmode, r_save_area,
   1195  1.1  mrg 				     GET_MODE_SIZE (Pmode)));
   1196  1.1  mrg 
   1197  1.1  mrg   crtl->has_nonlocal_goto = 1;
   1198  1.1  mrg 
   1199  1.1  mrg   /* ??? We no longer need to pass the static chain value, afaik.  */
   1200  1.1  mrg   if (targetm.have_nonlocal_goto ())
   1201  1.1  mrg     emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
   1202  1.1  mrg   else
   1203  1.1  mrg     {
   1204  1.1  mrg       emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
   1205  1.1  mrg       emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
   1206  1.1  mrg 
   1207  1.1  mrg       r_label = copy_to_reg (r_label);
   1208  1.1  mrg 
   1209  1.1  mrg       /* Restore the frame pointer and stack pointer.  We must use a
   1210  1.1  mrg 	 temporary since the setjmp buffer may be a local.  */
   1211  1.1  mrg       r_fp = copy_to_reg (r_fp);
   1212  1.1  mrg       emit_stack_restore (SAVE_NONLOCAL, r_sp);
   1213  1.1  mrg 
   1214  1.1  mrg       /* Ensure the frame pointer move is not optimized.  */
   1215  1.1  mrg       emit_insn (gen_blockage ());
   1216  1.1  mrg       emit_clobber (hard_frame_pointer_rtx);
   1217  1.1  mrg       emit_clobber (frame_pointer_rtx);
   1218  1.1  mrg       emit_move_insn (hard_frame_pointer_rtx, r_fp);
   1219  1.1  mrg 
   1220  1.1  mrg       /* USE of hard_frame_pointer_rtx added for consistency;
   1221  1.1  mrg 	 not clear if really needed.  */
   1222  1.1  mrg       emit_use (hard_frame_pointer_rtx);
   1223  1.1  mrg       emit_use (stack_pointer_rtx);
   1224  1.1  mrg 
   1225  1.1  mrg       /* If the architecture is using a GP register, we must
   1226  1.1  mrg 	 conservatively assume that the target function makes use of it.
   1227  1.1  mrg 	 The prologue of functions with nonlocal gotos must therefore
   1228  1.1  mrg 	 initialize the GP register to the appropriate value, and we
   1229  1.1  mrg 	 must then make sure that this value is live at the point
   1230  1.1  mrg 	 of the jump.  (Note that this doesn't necessarily apply
   1231  1.1  mrg 	 to targets with a nonlocal_goto pattern; they are free
   1232  1.1  mrg 	 to implement it in their own way.  Note also that this is
   1233  1.1  mrg 	 a no-op if the GP register is a global invariant.)  */
   1234  1.1  mrg       unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
   1235  1.1  mrg       if (regnum != INVALID_REGNUM && fixed_regs[regnum])
   1236  1.1  mrg 	emit_use (pic_offset_table_rtx);
   1237  1.1  mrg 
   1238  1.1  mrg       emit_indirect_jump (r_label);
   1239  1.1  mrg     }
   1240  1.1  mrg 
   1241  1.1  mrg   /* Search backwards to the jump insn and mark it as a
   1242  1.1  mrg      non-local goto.  */
   1243  1.1  mrg   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
   1244  1.1  mrg     {
   1245  1.1  mrg       if (JUMP_P (insn))
   1246  1.1  mrg 	{
   1247  1.1  mrg 	  add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
   1248  1.1  mrg 	  break;
   1249  1.1  mrg 	}
   1250  1.1  mrg       else if (CALL_P (insn))
   1251  1.1  mrg 	break;
   1252  1.1  mrg     }
   1253  1.1  mrg 
   1254  1.1  mrg   return const0_rtx;
   1255  1.1  mrg }
   1256  1.1  mrg 
   1257  1.1  mrg /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
   1258  1.1  mrg    (not all will be used on all machines) that was passed to __builtin_setjmp.
   1259  1.1  mrg    It updates the stack pointer in that block to the current value.  This is
   1260  1.1  mrg    also called directly by the SJLJ exception handling code.  */
   1261  1.1  mrg 
   1262  1.1  mrg void
   1263  1.1  mrg expand_builtin_update_setjmp_buf (rtx buf_addr)
   1264  1.1  mrg {
   1265  1.1  mrg   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
   1266  1.1  mrg   buf_addr = convert_memory_address (Pmode, buf_addr);
   1267  1.1  mrg   rtx stack_save
   1268  1.1  mrg     = gen_rtx_MEM (sa_mode,
   1269  1.1  mrg 		   memory_address
   1270  1.1  mrg 		   (sa_mode,
   1271  1.1  mrg 		    plus_constant (Pmode, buf_addr,
   1272  1.1  mrg 				   2 * GET_MODE_SIZE (Pmode))));
   1273  1.1  mrg 
   1274  1.1  mrg   emit_stack_save (SAVE_NONLOCAL, &stack_save);
   1275  1.1  mrg }
   1276  1.1  mrg 
   1277  1.1  mrg /* Expand a call to __builtin_prefetch.  For a target that does not support
   1278  1.1  mrg    data prefetch, evaluate the memory address argument in case it has side
   1279  1.1  mrg    effects.  */
   1280  1.1  mrg 
   1281  1.1  mrg static void
   1282  1.1  mrg expand_builtin_prefetch (tree exp)
   1283  1.1  mrg {
   1284  1.1  mrg   tree arg0, arg1, arg2;
   1285  1.1  mrg   int nargs;
   1286  1.1  mrg   rtx op0, op1, op2;
   1287  1.1  mrg 
   1288  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, 0))
   1289  1.1  mrg     return;
   1290  1.1  mrg 
   1291  1.1  mrg   arg0 = CALL_EXPR_ARG (exp, 0);
   1292  1.1  mrg 
   1293  1.1  mrg   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
   1294  1.1  mrg      zero (read) and argument 2 (locality) defaults to 3 (high degree of
   1295  1.1  mrg      locality).  */
   1296  1.1  mrg   nargs = call_expr_nargs (exp);
   1297  1.1  mrg   if (nargs > 1)
   1298  1.1  mrg     arg1 = CALL_EXPR_ARG (exp, 1);
   1299  1.1  mrg   else
   1300  1.1  mrg     arg1 = integer_zero_node;
   1301  1.1  mrg   if (nargs > 2)
   1302  1.1  mrg     arg2 = CALL_EXPR_ARG (exp, 2);
   1303  1.1  mrg   else
   1304  1.1  mrg     arg2 = integer_three_node;
   1305  1.1  mrg 
   1306  1.1  mrg   /* Argument 0 is an address.  */
   1307  1.1  mrg   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
   1308  1.1  mrg 
   1309  1.1  mrg   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
   1310  1.1  mrg   if (TREE_CODE (arg1) != INTEGER_CST)
   1311  1.1  mrg     {
   1312  1.1  mrg       error ("second argument to %<__builtin_prefetch%> must be a constant");
   1313  1.1  mrg       arg1 = integer_zero_node;
   1314  1.1  mrg     }
   1315  1.1  mrg   op1 = expand_normal (arg1);
   1316  1.1  mrg   /* Argument 1 must be either zero or one.  */
   1317  1.1  mrg   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
   1318  1.1  mrg     {
   1319  1.1  mrg       warning (0, "invalid second argument to %<__builtin_prefetch%>;"
   1320  1.1  mrg 	       " using zero");
   1321  1.1  mrg       op1 = const0_rtx;
   1322  1.1  mrg     }
   1323  1.1  mrg 
   1324  1.1  mrg   /* Argument 2 (locality) must be a compile-time constant int.  */
   1325  1.1  mrg   if (TREE_CODE (arg2) != INTEGER_CST)
   1326  1.1  mrg     {
   1327  1.1  mrg       error ("third argument to %<__builtin_prefetch%> must be a constant");
   1328  1.1  mrg       arg2 = integer_zero_node;
   1329  1.1  mrg     }
   1330  1.1  mrg   op2 = expand_normal (arg2);
   1331  1.1  mrg   /* Argument 2 must be 0, 1, 2, or 3.  */
   1332  1.1  mrg   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
   1333  1.1  mrg     {
   1334  1.1  mrg       warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
   1335  1.1  mrg       op2 = const0_rtx;
   1336  1.1  mrg     }
   1337  1.1  mrg 
   1338  1.1  mrg   if (targetm.have_prefetch ())
   1339  1.1  mrg     {
   1340  1.1  mrg       class expand_operand ops[3];
   1341  1.1  mrg 
   1342  1.1  mrg       create_address_operand (&ops[0], op0);
   1343  1.1  mrg       create_integer_operand (&ops[1], INTVAL (op1));
   1344  1.1  mrg       create_integer_operand (&ops[2], INTVAL (op2));
   1345  1.1  mrg       if (maybe_expand_insn (targetm.code_for_prefetch, 3, ops))
   1346  1.1  mrg 	return;
   1347  1.1  mrg     }
   1348  1.1  mrg 
   1349  1.1  mrg   /* Don't do anything with direct references to volatile memory, but
   1350  1.1  mrg      generate code to handle other side effects.  */
   1351  1.1  mrg   if (!MEM_P (op0) && side_effects_p (op0))
   1352  1.1  mrg     emit_insn (op0);
   1353  1.1  mrg }
   1354  1.1  mrg 
   1355  1.1  mrg /* Get a MEM rtx for expression EXP which is the address of an operand
   1356  1.1  mrg    to be used in a string instruction (cmpstrsi, cpymemsi, ..).  LEN is
   1357  1.1  mrg    the maximum length of the block of memory that might be accessed or
   1358  1.1  mrg    NULL if unknown.  */
   1359  1.1  mrg 
   1360  1.1  mrg rtx
   1361  1.1  mrg get_memory_rtx (tree exp, tree len)
   1362  1.1  mrg {
   1363  1.1  mrg   tree orig_exp = exp, base;
   1364  1.1  mrg   rtx addr, mem;
   1365  1.1  mrg 
   1366  1.1  mrg   /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
   1367  1.1  mrg      from its expression, for expr->a.b only <variable>.a.b is recorded.  */
   1368  1.1  mrg   if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
   1369  1.1  mrg     exp = TREE_OPERAND (exp, 0);
   1370  1.1  mrg 
   1371  1.1  mrg   addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
   1372  1.1  mrg   mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
   1373  1.1  mrg 
   1374  1.1  mrg   /* Get an expression we can use to find the attributes to assign to MEM.
   1375  1.1  mrg      First remove any nops.  */
   1376  1.1  mrg   while (CONVERT_EXPR_P (exp)
   1377  1.1  mrg 	 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
   1378  1.1  mrg     exp = TREE_OPERAND (exp, 0);
   1379  1.1  mrg 
   1380  1.1  mrg   /* Build a MEM_REF representing the whole accessed area as a byte blob,
   1381  1.1  mrg      (as builtin stringops may alias with anything).  */
   1382  1.1  mrg   exp = fold_build2 (MEM_REF,
   1383  1.1  mrg 		     build_array_type (char_type_node,
   1384  1.1  mrg 				       build_range_type (sizetype,
   1385  1.1  mrg 							 size_one_node, len)),
   1386  1.1  mrg 		     exp, build_int_cst (ptr_type_node, 0));
   1387  1.1  mrg 
   1388  1.1  mrg   /* If the MEM_REF has no acceptable address, try to get the base object
   1389  1.1  mrg      from the original address we got, and build an all-aliasing
   1390  1.1  mrg      unknown-sized access to that one.  */
   1391  1.1  mrg   if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
   1392  1.1  mrg     set_mem_attributes (mem, exp, 0);
   1393  1.1  mrg   else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
   1394  1.1  mrg 	   && (base = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
   1395  1.1  mrg 						      0))))
   1396  1.1  mrg     {
   1397  1.1  mrg       unsigned int align = get_pointer_alignment (TREE_OPERAND (exp, 0));
   1398  1.1  mrg       exp = build_fold_addr_expr (base);
   1399  1.1  mrg       exp = fold_build2 (MEM_REF,
   1400  1.1  mrg 			 build_array_type (char_type_node,
   1401  1.1  mrg 					   build_range_type (sizetype,
   1402  1.1  mrg 							     size_zero_node,
   1403  1.1  mrg 							     NULL)),
   1404  1.1  mrg 			 exp, build_int_cst (ptr_type_node, 0));
   1405  1.1  mrg       set_mem_attributes (mem, exp, 0);
   1406  1.1  mrg       /* Since we stripped parts make sure the offset is unknown and the
   1407  1.1  mrg 	 alignment is computed from the original address.  */
   1408  1.1  mrg       clear_mem_offset (mem);
   1409  1.1  mrg       set_mem_align (mem, align);
   1410  1.1  mrg     }
   1411  1.1  mrg   set_mem_alias_set (mem, 0);
   1412  1.1  mrg   return mem;
   1413  1.1  mrg }
   1414  1.1  mrg 
   1415  1.1  mrg /* Built-in functions to perform an untyped call and return.  */
   1417  1.1  mrg 
   1418  1.1  mrg #define apply_args_mode \
   1419  1.1  mrg   (this_target_builtins->x_apply_args_mode)
   1420  1.1  mrg #define apply_result_mode \
   1421  1.1  mrg   (this_target_builtins->x_apply_result_mode)
   1422  1.1  mrg 
   1423  1.1  mrg /* Return the size required for the block returned by __builtin_apply_args,
   1424  1.1  mrg    and initialize apply_args_mode.  */
   1425  1.1  mrg 
   1426  1.1  mrg static int
   1427  1.1  mrg apply_args_size (void)
   1428  1.1  mrg {
   1429  1.1  mrg   static int size = -1;
   1430  1.1  mrg   int align;
   1431  1.1  mrg   unsigned int regno;
   1432  1.1  mrg 
   1433  1.1  mrg   /* The values computed by this function never change.  */
   1434  1.1  mrg   if (size < 0)
   1435  1.1  mrg     {
   1436  1.1  mrg       /* The first value is the incoming arg-pointer.  */
   1437  1.1  mrg       size = GET_MODE_SIZE (Pmode);
   1438  1.1  mrg 
   1439  1.1  mrg       /* The second value is the structure value address unless this is
   1440  1.1  mrg 	 passed as an "invisible" first argument.  */
   1441  1.1  mrg       if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
   1442  1.1  mrg 	size += GET_MODE_SIZE (Pmode);
   1443  1.1  mrg 
   1444  1.1  mrg       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1445  1.1  mrg 	if (FUNCTION_ARG_REGNO_P (regno))
   1446  1.1  mrg 	  {
   1447  1.1  mrg 	    fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
   1448  1.1  mrg 
   1449  1.1  mrg 	    gcc_assert (mode != VOIDmode);
   1450  1.1  mrg 
   1451  1.1  mrg 	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
   1452  1.1  mrg 	    if (size % align != 0)
   1453  1.1  mrg 	      size = CEIL (size, align) * align;
   1454  1.1  mrg 	    size += GET_MODE_SIZE (mode);
   1455  1.1  mrg 	    apply_args_mode[regno] = mode;
   1456  1.1  mrg 	  }
   1457  1.1  mrg 	else
   1458  1.1  mrg 	  {
   1459  1.1  mrg 	    apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
   1460  1.1  mrg 	  }
   1461  1.1  mrg     }
   1462  1.1  mrg   return size;
   1463  1.1  mrg }
   1464  1.1  mrg 
   1465  1.1  mrg /* Return the size required for the block returned by __builtin_apply,
   1466  1.1  mrg    and initialize apply_result_mode.  */
   1467  1.1  mrg 
   1468  1.1  mrg static int
   1469  1.1  mrg apply_result_size (void)
   1470  1.1  mrg {
   1471  1.1  mrg   static int size = -1;
   1472  1.1  mrg   int align, regno;
   1473  1.1  mrg 
   1474  1.1  mrg   /* The values computed by this function never change.  */
   1475  1.1  mrg   if (size < 0)
   1476  1.1  mrg     {
   1477  1.1  mrg       size = 0;
   1478  1.1  mrg 
   1479  1.1  mrg       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1480  1.1  mrg 	if (targetm.calls.function_value_regno_p (regno))
   1481  1.1  mrg 	  {
   1482  1.1  mrg 	    fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
   1483  1.1  mrg 
   1484  1.1  mrg 	    gcc_assert (mode != VOIDmode);
   1485  1.1  mrg 
   1486  1.1  mrg 	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
   1487  1.1  mrg 	    if (size % align != 0)
   1488  1.1  mrg 	      size = CEIL (size, align) * align;
   1489  1.1  mrg 	    size += GET_MODE_SIZE (mode);
   1490  1.1  mrg 	    apply_result_mode[regno] = mode;
   1491  1.1  mrg 	  }
   1492  1.1  mrg 	else
   1493  1.1  mrg 	  apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
   1494  1.1  mrg 
   1495  1.1  mrg       /* Allow targets that use untyped_call and untyped_return to override
   1496  1.1  mrg 	 the size so that machine-specific information can be stored here.  */
   1497  1.1  mrg #ifdef APPLY_RESULT_SIZE
   1498  1.1  mrg       size = APPLY_RESULT_SIZE;
   1499  1.1  mrg #endif
   1500  1.1  mrg     }
   1501  1.1  mrg   return size;
   1502  1.1  mrg }
   1503  1.1  mrg 
   1504  1.1  mrg /* Create a vector describing the result block RESULT.  If SAVEP is true,
   1505  1.1  mrg    the result block is used to save the values; otherwise it is used to
   1506  1.1  mrg    restore the values.  */
   1507  1.1  mrg 
   1508  1.1  mrg static rtx
   1509  1.1  mrg result_vector (int savep, rtx result)
   1510  1.1  mrg {
   1511  1.1  mrg   int regno, size, align, nelts;
   1512  1.1  mrg   fixed_size_mode mode;
   1513  1.1  mrg   rtx reg, mem;
   1514  1.1  mrg   rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
   1515  1.1  mrg 
   1516  1.1  mrg   size = nelts = 0;
   1517  1.1  mrg   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1518  1.1  mrg     if ((mode = apply_result_mode[regno]) != VOIDmode)
   1519  1.1  mrg       {
   1520  1.1  mrg 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
   1521  1.1  mrg 	if (size % align != 0)
   1522  1.1  mrg 	  size = CEIL (size, align) * align;
   1523  1.1  mrg 	reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
   1524  1.1  mrg 	mem = adjust_address (result, mode, size);
   1525  1.1  mrg 	savevec[nelts++] = (savep
   1526  1.1  mrg 			    ? gen_rtx_SET (mem, reg)
   1527  1.1  mrg 			    : gen_rtx_SET (reg, mem));
   1528  1.1  mrg 	size += GET_MODE_SIZE (mode);
   1529  1.1  mrg       }
   1530  1.1  mrg   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
   1531  1.1  mrg }
   1532  1.1  mrg 
   1533  1.1  mrg /* Save the state required to perform an untyped call with the same
   1534  1.1  mrg    arguments as were passed to the current function.  */
   1535  1.1  mrg 
   1536  1.1  mrg static rtx
   1537  1.1  mrg expand_builtin_apply_args_1 (void)
   1538  1.1  mrg {
   1539  1.1  mrg   rtx registers, tem;
   1540  1.1  mrg   int size, align, regno;
   1541  1.1  mrg   fixed_size_mode mode;
   1542  1.1  mrg   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
   1543  1.1  mrg 
   1544  1.1  mrg   /* Create a block where the arg-pointer, structure value address,
   1545  1.1  mrg      and argument registers can be saved.  */
   1546  1.1  mrg   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
   1547  1.1  mrg 
   1548  1.1  mrg   /* Walk past the arg-pointer and structure value address.  */
   1549  1.1  mrg   size = GET_MODE_SIZE (Pmode);
   1550  1.1  mrg   if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
   1551  1.1  mrg     size += GET_MODE_SIZE (Pmode);
   1552  1.1  mrg 
   1553  1.1  mrg   /* Save each register used in calling a function to the block.  */
   1554  1.1  mrg   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1555  1.1  mrg     if ((mode = apply_args_mode[regno]) != VOIDmode)
   1556  1.1  mrg       {
   1557  1.1  mrg 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
   1558  1.1  mrg 	if (size % align != 0)
   1559  1.1  mrg 	  size = CEIL (size, align) * align;
   1560  1.1  mrg 
   1561  1.1  mrg 	tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
   1562  1.1  mrg 
   1563  1.1  mrg 	emit_move_insn (adjust_address (registers, mode, size), tem);
   1564  1.1  mrg 	size += GET_MODE_SIZE (mode);
   1565  1.1  mrg       }
   1566  1.1  mrg 
   1567  1.1  mrg   /* Save the arg pointer to the block.  */
   1568  1.1  mrg   tem = copy_to_reg (crtl->args.internal_arg_pointer);
   1569  1.1  mrg   /* We need the pointer as the caller actually passed them to us, not
   1570  1.1  mrg      as we might have pretended they were passed.  Make sure it's a valid
   1571  1.1  mrg      operand, as emit_move_insn isn't expected to handle a PLUS.  */
   1572  1.1  mrg   if (STACK_GROWS_DOWNWARD)
   1573  1.1  mrg     tem
   1574  1.1  mrg       = force_operand (plus_constant (Pmode, tem,
   1575  1.1  mrg 				      crtl->args.pretend_args_size),
   1576  1.1  mrg 		       NULL_RTX);
   1577  1.1  mrg   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
   1578  1.1  mrg 
   1579  1.1  mrg   size = GET_MODE_SIZE (Pmode);
   1580  1.1  mrg 
   1581  1.1  mrg   /* Save the structure value address unless this is passed as an
   1582  1.1  mrg      "invisible" first argument.  */
   1583  1.1  mrg   if (struct_incoming_value)
   1584  1.1  mrg     emit_move_insn (adjust_address (registers, Pmode, size),
   1585  1.1  mrg 		    copy_to_reg (struct_incoming_value));
   1586  1.1  mrg 
   1587  1.1  mrg   /* Return the address of the block.  */
   1588  1.1  mrg   return copy_addr_to_reg (XEXP (registers, 0));
   1589  1.1  mrg }
   1590  1.1  mrg 
   1591  1.1  mrg /* __builtin_apply_args returns block of memory allocated on
   1592  1.1  mrg    the stack into which is stored the arg pointer, structure
   1593  1.1  mrg    value address, static chain, and all the registers that might
   1594  1.1  mrg    possibly be used in performing a function call.  The code is
   1595  1.1  mrg    moved to the start of the function so the incoming values are
   1596  1.1  mrg    saved.  */
   1597  1.1  mrg 
   1598  1.1  mrg static rtx
   1599  1.1  mrg expand_builtin_apply_args (void)
   1600  1.1  mrg {
   1601  1.1  mrg   /* Don't do __builtin_apply_args more than once in a function.
   1602  1.1  mrg      Save the result of the first call and reuse it.  */
   1603  1.1  mrg   if (apply_args_value != 0)
   1604  1.1  mrg     return apply_args_value;
   1605  1.1  mrg   {
   1606  1.1  mrg     /* When this function is called, it means that registers must be
   1607  1.1  mrg        saved on entry to this function.  So we migrate the
   1608  1.1  mrg        call to the first insn of this function.  */
   1609  1.1  mrg     rtx temp;
   1610  1.1  mrg 
   1611  1.1  mrg     start_sequence ();
   1612  1.1  mrg     temp = expand_builtin_apply_args_1 ();
   1613  1.1  mrg     rtx_insn *seq = get_insns ();
   1614  1.1  mrg     end_sequence ();
   1615  1.1  mrg 
   1616  1.1  mrg     apply_args_value = temp;
   1617  1.1  mrg 
   1618  1.1  mrg     /* Put the insns after the NOTE that starts the function.
   1619  1.1  mrg        If this is inside a start_sequence, make the outer-level insn
   1620  1.1  mrg        chain current, so the code is placed at the start of the
   1621  1.1  mrg        function.  If internal_arg_pointer is a non-virtual pseudo,
   1622  1.1  mrg        it needs to be placed after the function that initializes
   1623  1.1  mrg        that pseudo.  */
   1624  1.1  mrg     push_topmost_sequence ();
   1625  1.1  mrg     if (REG_P (crtl->args.internal_arg_pointer)
   1626  1.1  mrg 	&& REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
   1627  1.1  mrg       emit_insn_before (seq, parm_birth_insn);
   1628  1.1  mrg     else
   1629  1.1  mrg       emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
   1630  1.1  mrg     pop_topmost_sequence ();
   1631  1.1  mrg     return temp;
   1632  1.1  mrg   }
   1633  1.1  mrg }
   1634  1.1  mrg 
   1635  1.1  mrg /* Perform an untyped call and save the state required to perform an
   1636  1.1  mrg    untyped return of whatever value was returned by the given function.  */
   1637  1.1  mrg 
   1638  1.1  mrg static rtx
   1639  1.1  mrg expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
   1640  1.1  mrg {
   1641  1.1  mrg   int size, align, regno;
   1642  1.1  mrg   fixed_size_mode mode;
   1643  1.1  mrg   rtx incoming_args, result, reg, dest, src;
   1644  1.1  mrg   rtx_call_insn *call_insn;
   1645  1.1  mrg   rtx old_stack_level = 0;
   1646  1.1  mrg   rtx call_fusage = 0;
   1647  1.1  mrg   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
   1648  1.1  mrg 
   1649  1.1  mrg   arguments = convert_memory_address (Pmode, arguments);
   1650  1.1  mrg 
   1651  1.1  mrg   /* Create a block where the return registers can be saved.  */
   1652  1.1  mrg   result = assign_stack_local (BLKmode, apply_result_size (), -1);
   1653  1.1  mrg 
   1654  1.1  mrg   /* Fetch the arg pointer from the ARGUMENTS block.  */
   1655  1.1  mrg   incoming_args = gen_reg_rtx (Pmode);
   1656  1.1  mrg   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
   1657  1.1  mrg   if (!STACK_GROWS_DOWNWARD)
   1658  1.1  mrg     incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
   1659  1.1  mrg 					 incoming_args, 0, OPTAB_LIB_WIDEN);
   1660  1.1  mrg 
   1661  1.1  mrg   /* Push a new argument block and copy the arguments.  Do not allow
   1662  1.1  mrg      the (potential) memcpy call below to interfere with our stack
   1663  1.1  mrg      manipulations.  */
   1664  1.1  mrg   do_pending_stack_adjust ();
   1665  1.1  mrg   NO_DEFER_POP;
   1666  1.1  mrg 
   1667  1.1  mrg   /* Save the stack with nonlocal if available.  */
   1668  1.1  mrg   if (targetm.have_save_stack_nonlocal ())
   1669  1.1  mrg     emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
   1670  1.1  mrg   else
   1671  1.1  mrg     emit_stack_save (SAVE_BLOCK, &old_stack_level);
   1672  1.1  mrg 
   1673  1.1  mrg   /* Allocate a block of memory onto the stack and copy the memory
   1674  1.1  mrg      arguments to the outgoing arguments address.  We can pass TRUE
   1675  1.1  mrg      as the 4th argument because we just saved the stack pointer
   1676  1.1  mrg      and will restore it right after the call.  */
   1677  1.1  mrg   allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
   1678  1.1  mrg 
   1679  1.1  mrg   /* Set DRAP flag to true, even though allocate_dynamic_stack_space
   1680  1.1  mrg      may have already set current_function_calls_alloca to true.
   1681  1.1  mrg      current_function_calls_alloca won't be set if argsize is zero,
   1682  1.1  mrg      so we have to guarantee need_drap is true here.  */
   1683  1.1  mrg   if (SUPPORTS_STACK_ALIGNMENT)
   1684  1.1  mrg     crtl->need_drap = true;
   1685  1.1  mrg 
   1686  1.1  mrg   dest = virtual_outgoing_args_rtx;
   1687  1.1  mrg   if (!STACK_GROWS_DOWNWARD)
   1688  1.1  mrg     {
   1689  1.1  mrg       if (CONST_INT_P (argsize))
   1690  1.1  mrg 	dest = plus_constant (Pmode, dest, -INTVAL (argsize));
   1691  1.1  mrg       else
   1692  1.1  mrg 	dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
   1693  1.1  mrg     }
   1694  1.1  mrg   dest = gen_rtx_MEM (BLKmode, dest);
   1695  1.1  mrg   set_mem_align (dest, PARM_BOUNDARY);
   1696  1.1  mrg   src = gen_rtx_MEM (BLKmode, incoming_args);
   1697  1.1  mrg   set_mem_align (src, PARM_BOUNDARY);
   1698  1.1  mrg   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
   1699  1.1  mrg 
   1700  1.1  mrg   /* Refer to the argument block.  */
   1701  1.1  mrg   apply_args_size ();
   1702  1.1  mrg   arguments = gen_rtx_MEM (BLKmode, arguments);
   1703  1.1  mrg   set_mem_align (arguments, PARM_BOUNDARY);
   1704  1.1  mrg 
   1705  1.1  mrg   /* Walk past the arg-pointer and structure value address.  */
   1706  1.1  mrg   size = GET_MODE_SIZE (Pmode);
   1707  1.1  mrg   if (struct_value)
   1708  1.1  mrg     size += GET_MODE_SIZE (Pmode);
   1709  1.1  mrg 
   1710  1.1  mrg   /* Restore each of the registers previously saved.  Make USE insns
   1711  1.1  mrg      for each of these registers for use in making the call.  */
   1712  1.1  mrg   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1713  1.1  mrg     if ((mode = apply_args_mode[regno]) != VOIDmode)
   1714  1.1  mrg       {
   1715  1.1  mrg 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
   1716  1.1  mrg 	if (size % align != 0)
   1717  1.1  mrg 	  size = CEIL (size, align) * align;
   1718  1.1  mrg 	reg = gen_rtx_REG (mode, regno);
   1719  1.1  mrg 	emit_move_insn (reg, adjust_address (arguments, mode, size));
   1720  1.1  mrg 	use_reg (&call_fusage, reg);
   1721  1.1  mrg 	size += GET_MODE_SIZE (mode);
   1722  1.1  mrg       }
   1723  1.1  mrg 
   1724  1.1  mrg   /* Restore the structure value address unless this is passed as an
   1725  1.1  mrg      "invisible" first argument.  */
   1726  1.1  mrg   size = GET_MODE_SIZE (Pmode);
   1727  1.1  mrg   if (struct_value)
   1728  1.1  mrg     {
   1729  1.1  mrg       rtx value = gen_reg_rtx (Pmode);
   1730  1.1  mrg       emit_move_insn (value, adjust_address (arguments, Pmode, size));
   1731  1.1  mrg       emit_move_insn (struct_value, value);
   1732  1.1  mrg       if (REG_P (struct_value))
   1733  1.1  mrg 	use_reg (&call_fusage, struct_value);
   1734  1.1  mrg     }
   1735  1.1  mrg 
   1736  1.1  mrg   /* All arguments and registers used for the call are set up by now!  */
   1737  1.1  mrg   function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
   1738  1.1  mrg 
   1739  1.1  mrg   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
   1740  1.1  mrg      and we don't want to load it into a register as an optimization,
   1741  1.1  mrg      because prepare_call_address already did it if it should be done.  */
   1742  1.1  mrg   if (GET_CODE (function) != SYMBOL_REF)
   1743  1.1  mrg     function = memory_address (FUNCTION_MODE, function);
   1744  1.1  mrg 
   1745  1.1  mrg   /* Generate the actual call instruction and save the return value.  */
   1746  1.1  mrg   if (targetm.have_untyped_call ())
   1747  1.1  mrg     {
   1748  1.1  mrg       rtx mem = gen_rtx_MEM (FUNCTION_MODE, function);
   1749  1.1  mrg       rtx_insn *seq = targetm.gen_untyped_call (mem, result,
   1750  1.1  mrg 						result_vector (1, result));
   1751  1.1  mrg       for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
   1752  1.1  mrg 	if (CALL_P (insn))
   1753  1.1  mrg 	  add_reg_note (insn, REG_UNTYPED_CALL, NULL_RTX);
   1754  1.1  mrg       emit_insn (seq);
   1755  1.1  mrg     }
   1756  1.1  mrg   else if (targetm.have_call_value ())
   1757  1.1  mrg     {
   1758  1.1  mrg       rtx valreg = 0;
   1759  1.1  mrg 
   1760  1.1  mrg       /* Locate the unique return register.  It is not possible to
   1761  1.1  mrg 	 express a call that sets more than one return register using
   1762  1.1  mrg 	 call_value; use untyped_call for that.  In fact, untyped_call
   1763  1.1  mrg 	 only needs to save the return registers in the given block.  */
   1764  1.1  mrg       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1765  1.1  mrg 	if ((mode = apply_result_mode[regno]) != VOIDmode)
   1766  1.1  mrg 	  {
   1767  1.1  mrg 	    gcc_assert (!valreg); /* have_untyped_call required.  */
   1768  1.1  mrg 
   1769  1.1  mrg 	    valreg = gen_rtx_REG (mode, regno);
   1770  1.1  mrg 	  }
   1771  1.1  mrg 
   1772  1.1  mrg       emit_insn (targetm.gen_call_value (valreg,
   1773  1.1  mrg 					 gen_rtx_MEM (FUNCTION_MODE, function),
   1774  1.1  mrg 					 const0_rtx, NULL_RTX, const0_rtx));
   1775  1.1  mrg 
   1776  1.1  mrg       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
   1777  1.1  mrg     }
   1778  1.1  mrg   else
   1779  1.1  mrg     gcc_unreachable ();
   1780  1.1  mrg 
   1781  1.1  mrg   /* Find the CALL insn we just emitted, and attach the register usage
   1782  1.1  mrg      information.  */
   1783  1.1  mrg   call_insn = last_call_insn ();
   1784  1.1  mrg   add_function_usage_to (call_insn, call_fusage);
   1785  1.1  mrg 
   1786  1.1  mrg   /* Restore the stack.  */
   1787  1.1  mrg   if (targetm.have_save_stack_nonlocal ())
   1788  1.1  mrg     emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
   1789  1.1  mrg   else
   1790  1.1  mrg     emit_stack_restore (SAVE_BLOCK, old_stack_level);
   1791  1.1  mrg   fixup_args_size_notes (call_insn, get_last_insn (), 0);
   1792  1.1  mrg 
   1793  1.1  mrg   OK_DEFER_POP;
   1794  1.1  mrg 
   1795  1.1  mrg   /* Return the address of the result block.  */
   1796  1.1  mrg   result = copy_addr_to_reg (XEXP (result, 0));
   1797  1.1  mrg   return convert_memory_address (ptr_mode, result);
   1798  1.1  mrg }
   1799  1.1  mrg 
   1800  1.1  mrg /* Perform an untyped return.  */
   1801  1.1  mrg 
   1802  1.1  mrg static void
   1803  1.1  mrg expand_builtin_return (rtx result)
   1804  1.1  mrg {
   1805  1.1  mrg   int size, align, regno;
   1806  1.1  mrg   fixed_size_mode mode;
   1807  1.1  mrg   rtx reg;
   1808  1.1  mrg   rtx_insn *call_fusage = 0;
   1809  1.1  mrg 
   1810  1.1  mrg   result = convert_memory_address (Pmode, result);
   1811  1.1  mrg 
   1812  1.1  mrg   apply_result_size ();
   1813  1.1  mrg   result = gen_rtx_MEM (BLKmode, result);
   1814  1.1  mrg 
   1815  1.1  mrg   if (targetm.have_untyped_return ())
   1816  1.1  mrg     {
   1817  1.1  mrg       rtx vector = result_vector (0, result);
   1818  1.1  mrg       emit_jump_insn (targetm.gen_untyped_return (result, vector));
   1819  1.1  mrg       emit_barrier ();
   1820  1.1  mrg       return;
   1821  1.1  mrg     }
   1822  1.1  mrg 
   1823  1.1  mrg   /* Restore the return value and note that each value is used.  */
   1824  1.1  mrg   size = 0;
   1825  1.1  mrg   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   1826  1.1  mrg     if ((mode = apply_result_mode[regno]) != VOIDmode)
   1827  1.1  mrg       {
   1828  1.1  mrg 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
   1829  1.1  mrg 	if (size % align != 0)
   1830  1.1  mrg 	  size = CEIL (size, align) * align;
   1831  1.1  mrg 	reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
   1832  1.1  mrg 	emit_move_insn (reg, adjust_address (result, mode, size));
   1833  1.1  mrg 
   1834  1.1  mrg 	push_to_sequence (call_fusage);
   1835  1.1  mrg 	emit_use (reg);
   1836  1.1  mrg 	call_fusage = get_insns ();
   1837  1.1  mrg 	end_sequence ();
   1838  1.1  mrg 	size += GET_MODE_SIZE (mode);
   1839  1.1  mrg       }
   1840  1.1  mrg 
   1841  1.1  mrg   /* Put the USE insns before the return.  */
   1842  1.1  mrg   emit_insn (call_fusage);
   1843  1.1  mrg 
   1844  1.1  mrg   /* Return whatever values was restored by jumping directly to the end
   1845  1.1  mrg      of the function.  */
   1846  1.1  mrg   expand_naked_return ();
   1847  1.1  mrg }
   1848  1.1  mrg 
   1849  1.1  mrg /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
   1850  1.1  mrg 
   1851  1.1  mrg static enum type_class
   1852  1.1  mrg type_to_class (tree type)
   1853  1.1  mrg {
   1854  1.1  mrg   switch (TREE_CODE (type))
   1855  1.1  mrg     {
   1856  1.1  mrg     case VOID_TYPE:	   return void_type_class;
   1857  1.1  mrg     case INTEGER_TYPE:	   return integer_type_class;
   1858  1.1  mrg     case ENUMERAL_TYPE:	   return enumeral_type_class;
   1859  1.1  mrg     case BOOLEAN_TYPE:	   return boolean_type_class;
   1860  1.1  mrg     case POINTER_TYPE:	   return pointer_type_class;
   1861  1.1  mrg     case REFERENCE_TYPE:   return reference_type_class;
   1862  1.1  mrg     case OFFSET_TYPE:	   return offset_type_class;
   1863  1.1  mrg     case REAL_TYPE:	   return real_type_class;
   1864  1.1  mrg     case COMPLEX_TYPE:	   return complex_type_class;
   1865  1.1  mrg     case FUNCTION_TYPE:	   return function_type_class;
   1866  1.1  mrg     case METHOD_TYPE:	   return method_type_class;
   1867  1.1  mrg     case RECORD_TYPE:	   return record_type_class;
   1868  1.1  mrg     case UNION_TYPE:
   1869  1.1  mrg     case QUAL_UNION_TYPE:  return union_type_class;
   1870  1.1  mrg     case ARRAY_TYPE:	   return (TYPE_STRING_FLAG (type)
   1871  1.1  mrg 				   ? string_type_class : array_type_class);
   1872  1.1  mrg     case LANG_TYPE:	   return lang_type_class;
   1873  1.1  mrg     case OPAQUE_TYPE:      return opaque_type_class;
   1874  1.1  mrg     default:		   return no_type_class;
   1875  1.1  mrg     }
   1876  1.1  mrg }
   1877  1.1  mrg 
   1878  1.1  mrg /* Expand a call EXP to __builtin_classify_type.  */
   1879  1.1  mrg 
   1880  1.1  mrg static rtx
   1881  1.1  mrg expand_builtin_classify_type (tree exp)
   1882  1.1  mrg {
   1883  1.1  mrg   if (call_expr_nargs (exp))
   1884  1.1  mrg     return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
   1885  1.1  mrg   return GEN_INT (no_type_class);
   1886  1.1  mrg }
   1887  1.1  mrg 
   1888  1.1  mrg /* This helper macro, meant to be used in mathfn_built_in below, determines
   1889  1.1  mrg    which among a set of builtin math functions is appropriate for a given type
   1890  1.1  mrg    mode.  The `F' (float) and `L' (long double) are automatically generated
   1891  1.1  mrg    from the 'double' case.  If a function supports the _Float<N> and _Float<N>X
   1892  1.1  mrg    types, there are additional types that are considered with 'F32', 'F64',
   1893  1.1  mrg    'F128', etc. suffixes.  */
   1894  1.1  mrg #define CASE_MATHFN(MATHFN) \
   1895  1.1  mrg   CASE_CFN_##MATHFN: \
   1896  1.1  mrg   fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
   1897  1.1  mrg   fcodel = BUILT_IN_##MATHFN##L ; break;
   1898  1.1  mrg /* Similar to the above, but also add support for the _Float<N> and _Float<N>X
   1899  1.1  mrg    types.  */
   1900  1.1  mrg #define CASE_MATHFN_FLOATN(MATHFN) \
   1901  1.1  mrg   CASE_CFN_##MATHFN: \
   1902  1.1  mrg   fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
   1903  1.1  mrg   fcodel = BUILT_IN_##MATHFN##L ; fcodef16 = BUILT_IN_##MATHFN##F16 ; \
   1904  1.1  mrg   fcodef32 = BUILT_IN_##MATHFN##F32; fcodef64 = BUILT_IN_##MATHFN##F64 ; \
   1905  1.1  mrg   fcodef128 = BUILT_IN_##MATHFN##F128 ; fcodef32x = BUILT_IN_##MATHFN##F32X ; \
   1906  1.1  mrg   fcodef64x = BUILT_IN_##MATHFN##F64X ; fcodef128x = BUILT_IN_##MATHFN##F128X ;\
   1907  1.1  mrg   break;
   1908  1.1  mrg /* Similar to above, but appends _R after any F/L suffix.  */
   1909  1.1  mrg #define CASE_MATHFN_REENT(MATHFN) \
   1910  1.1  mrg   case CFN_BUILT_IN_##MATHFN##_R: \
   1911  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F_R: \
   1912  1.1  mrg   case CFN_BUILT_IN_##MATHFN##L_R: \
   1913  1.1  mrg   fcode = BUILT_IN_##MATHFN##_R; fcodef = BUILT_IN_##MATHFN##F_R ; \
   1914  1.1  mrg   fcodel = BUILT_IN_##MATHFN##L_R ; break;
   1915  1.1  mrg 
   1916  1.1  mrg /* Return a function equivalent to FN but operating on floating-point
   1917  1.1  mrg    values of type TYPE, or END_BUILTINS if no such function exists.
   1918  1.1  mrg    This is purely an operation on function codes; it does not guarantee
   1919  1.1  mrg    that the target actually has an implementation of the function.  */
   1920  1.1  mrg 
   1921  1.1  mrg static built_in_function
   1922  1.1  mrg mathfn_built_in_2 (tree type, combined_fn fn)
   1923  1.1  mrg {
   1924  1.1  mrg   tree mtype;
   1925  1.1  mrg   built_in_function fcode, fcodef, fcodel;
   1926  1.1  mrg   built_in_function fcodef16 = END_BUILTINS;
   1927  1.1  mrg   built_in_function fcodef32 = END_BUILTINS;
   1928  1.1  mrg   built_in_function fcodef64 = END_BUILTINS;
   1929  1.1  mrg   built_in_function fcodef128 = END_BUILTINS;
   1930  1.1  mrg   built_in_function fcodef32x = END_BUILTINS;
   1931  1.1  mrg   built_in_function fcodef64x = END_BUILTINS;
   1932  1.1  mrg   built_in_function fcodef128x = END_BUILTINS;
   1933  1.1  mrg 
   1934  1.1  mrg   switch (fn)
   1935  1.1  mrg     {
   1936  1.1  mrg #define SEQ_OF_CASE_MATHFN			\
   1937  1.1  mrg     CASE_MATHFN (ACOS)				\
   1938  1.1  mrg     CASE_MATHFN (ACOSH)				\
   1939  1.1  mrg     CASE_MATHFN (ASIN)				\
   1940  1.1  mrg     CASE_MATHFN (ASINH)				\
   1941  1.1  mrg     CASE_MATHFN (ATAN)				\
   1942  1.1  mrg     CASE_MATHFN (ATAN2)				\
   1943  1.1  mrg     CASE_MATHFN (ATANH)				\
   1944  1.1  mrg     CASE_MATHFN (CBRT)				\
   1945  1.1  mrg     CASE_MATHFN_FLOATN (CEIL)			\
   1946  1.1  mrg     CASE_MATHFN (CEXPI)				\
   1947  1.1  mrg     CASE_MATHFN_FLOATN (COPYSIGN)		\
   1948  1.1  mrg     CASE_MATHFN (COS)				\
   1949  1.1  mrg     CASE_MATHFN (COSH)				\
   1950  1.1  mrg     CASE_MATHFN (DREM)				\
   1951  1.1  mrg     CASE_MATHFN (ERF)				\
   1952  1.1  mrg     CASE_MATHFN (ERFC)				\
   1953  1.1  mrg     CASE_MATHFN (EXP)				\
   1954  1.1  mrg     CASE_MATHFN (EXP10)				\
   1955  1.1  mrg     CASE_MATHFN (EXP2)				\
   1956  1.1  mrg     CASE_MATHFN (EXPM1)				\
   1957  1.1  mrg     CASE_MATHFN (FABS)				\
   1958  1.1  mrg     CASE_MATHFN (FDIM)				\
   1959  1.1  mrg     CASE_MATHFN_FLOATN (FLOOR)			\
   1960  1.1  mrg     CASE_MATHFN_FLOATN (FMA)			\
   1961  1.1  mrg     CASE_MATHFN_FLOATN (FMAX)			\
   1962  1.1  mrg     CASE_MATHFN_FLOATN (FMIN)			\
   1963  1.1  mrg     CASE_MATHFN (FMOD)				\
   1964  1.1  mrg     CASE_MATHFN (FREXP)				\
   1965  1.1  mrg     CASE_MATHFN (GAMMA)				\
   1966  1.1  mrg     CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */	\
   1967  1.1  mrg     CASE_MATHFN (HUGE_VAL)			\
   1968  1.1  mrg     CASE_MATHFN (HYPOT)				\
   1969  1.1  mrg     CASE_MATHFN (ILOGB)				\
   1970  1.1  mrg     CASE_MATHFN (ICEIL)				\
   1971  1.1  mrg     CASE_MATHFN (IFLOOR)			\
   1972  1.1  mrg     CASE_MATHFN (INF)				\
   1973  1.1  mrg     CASE_MATHFN (IRINT)				\
   1974  1.1  mrg     CASE_MATHFN (IROUND)			\
   1975  1.1  mrg     CASE_MATHFN (ISINF)				\
   1976  1.1  mrg     CASE_MATHFN (J0)				\
   1977  1.1  mrg     CASE_MATHFN (J1)				\
   1978  1.1  mrg     CASE_MATHFN (JN)				\
   1979  1.1  mrg     CASE_MATHFN (LCEIL)				\
   1980  1.1  mrg     CASE_MATHFN (LDEXP)				\
   1981  1.1  mrg     CASE_MATHFN (LFLOOR)			\
   1982  1.1  mrg     CASE_MATHFN (LGAMMA)			\
   1983  1.1  mrg     CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */	\
   1984  1.1  mrg     CASE_MATHFN (LLCEIL)			\
   1985  1.1  mrg     CASE_MATHFN (LLFLOOR)			\
   1986  1.1  mrg     CASE_MATHFN (LLRINT)			\
   1987  1.1  mrg     CASE_MATHFN (LLROUND)			\
   1988  1.1  mrg     CASE_MATHFN (LOG)				\
   1989  1.1  mrg     CASE_MATHFN (LOG10)				\
   1990  1.1  mrg     CASE_MATHFN (LOG1P)				\
   1991  1.1  mrg     CASE_MATHFN (LOG2)				\
   1992  1.1  mrg     CASE_MATHFN (LOGB)				\
   1993  1.1  mrg     CASE_MATHFN (LRINT)				\
   1994  1.1  mrg     CASE_MATHFN (LROUND)			\
   1995  1.1  mrg     CASE_MATHFN (MODF)				\
   1996  1.1  mrg     CASE_MATHFN (NAN)				\
   1997  1.1  mrg     CASE_MATHFN (NANS)				\
   1998  1.1  mrg     CASE_MATHFN_FLOATN (NEARBYINT)		\
   1999  1.1  mrg     CASE_MATHFN (NEXTAFTER)			\
   2000  1.1  mrg     CASE_MATHFN (NEXTTOWARD)			\
   2001  1.1  mrg     CASE_MATHFN (POW)				\
   2002  1.1  mrg     CASE_MATHFN (POWI)				\
   2003  1.1  mrg     CASE_MATHFN (POW10)				\
   2004  1.1  mrg     CASE_MATHFN (REMAINDER)			\
   2005  1.1  mrg     CASE_MATHFN (REMQUO)			\
   2006  1.1  mrg     CASE_MATHFN_FLOATN (RINT)			\
   2007  1.1  mrg     CASE_MATHFN_FLOATN (ROUND)			\
   2008  1.1  mrg     CASE_MATHFN_FLOATN (ROUNDEVEN)		\
   2009  1.1  mrg     CASE_MATHFN (SCALB)				\
   2010  1.1  mrg     CASE_MATHFN (SCALBLN)			\
   2011  1.1  mrg     CASE_MATHFN (SCALBN)			\
   2012  1.1  mrg     CASE_MATHFN (SIGNBIT)			\
   2013  1.1  mrg     CASE_MATHFN (SIGNIFICAND)			\
   2014  1.1  mrg     CASE_MATHFN (SIN)				\
   2015  1.1  mrg     CASE_MATHFN (SINCOS)			\
   2016  1.1  mrg     CASE_MATHFN (SINH)				\
   2017  1.1  mrg     CASE_MATHFN_FLOATN (SQRT)			\
   2018  1.1  mrg     CASE_MATHFN (TAN)				\
   2019  1.1  mrg     CASE_MATHFN (TANH)				\
   2020  1.1  mrg     CASE_MATHFN (TGAMMA)			\
   2021  1.1  mrg     CASE_MATHFN_FLOATN (TRUNC)			\
   2022  1.1  mrg     CASE_MATHFN (Y0)				\
   2023  1.1  mrg     CASE_MATHFN (Y1)				\
   2024  1.1  mrg     CASE_MATHFN (YN)
   2025  1.1  mrg 
   2026  1.1  mrg     SEQ_OF_CASE_MATHFN
   2027  1.1  mrg 
   2028  1.1  mrg     default:
   2029  1.1  mrg       return END_BUILTINS;
   2030  1.1  mrg     }
   2031  1.1  mrg 
   2032  1.1  mrg   mtype = TYPE_MAIN_VARIANT (type);
   2033  1.1  mrg   if (mtype == double_type_node)
   2034  1.1  mrg     return fcode;
   2035  1.1  mrg   else if (mtype == float_type_node)
   2036  1.1  mrg     return fcodef;
   2037  1.1  mrg   else if (mtype == long_double_type_node)
   2038  1.1  mrg     return fcodel;
   2039  1.1  mrg   else if (mtype == float16_type_node)
   2040  1.1  mrg     return fcodef16;
   2041  1.1  mrg   else if (mtype == float32_type_node)
   2042  1.1  mrg     return fcodef32;
   2043  1.1  mrg   else if (mtype == float64_type_node)
   2044  1.1  mrg     return fcodef64;
   2045  1.1  mrg   else if (mtype == float128_type_node)
   2046  1.1  mrg     return fcodef128;
   2047  1.1  mrg   else if (mtype == float32x_type_node)
   2048  1.1  mrg     return fcodef32x;
   2049  1.1  mrg   else if (mtype == float64x_type_node)
   2050  1.1  mrg     return fcodef64x;
   2051  1.1  mrg   else if (mtype == float128x_type_node)
   2052  1.1  mrg     return fcodef128x;
   2053  1.1  mrg   else
   2054  1.1  mrg     return END_BUILTINS;
   2055  1.1  mrg }
   2056  1.1  mrg 
   2057  1.1  mrg #undef CASE_MATHFN
   2058  1.1  mrg #undef CASE_MATHFN_FLOATN
   2059  1.1  mrg #undef CASE_MATHFN_REENT
   2060  1.1  mrg 
   2061  1.1  mrg /* Return mathematic function equivalent to FN but operating directly on TYPE,
   2062  1.1  mrg    if available.  If IMPLICIT_P is true use the implicit builtin declaration,
   2063  1.1  mrg    otherwise use the explicit declaration.  If we can't do the conversion,
   2064  1.1  mrg    return null.  */
   2065  1.1  mrg 
   2066  1.1  mrg static tree
   2067  1.1  mrg mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
   2068  1.1  mrg {
   2069  1.1  mrg   built_in_function fcode2 = mathfn_built_in_2 (type, fn);
   2070  1.1  mrg   if (fcode2 == END_BUILTINS)
   2071  1.1  mrg     return NULL_TREE;
   2072  1.1  mrg 
   2073  1.1  mrg   if (implicit_p && !builtin_decl_implicit_p (fcode2))
   2074  1.1  mrg     return NULL_TREE;
   2075  1.1  mrg 
   2076  1.1  mrg   return builtin_decl_explicit (fcode2);
   2077  1.1  mrg }
   2078  1.1  mrg 
   2079  1.1  mrg /* Like mathfn_built_in_1, but always use the implicit array.  */
   2080  1.1  mrg 
   2081  1.1  mrg tree
   2082  1.1  mrg mathfn_built_in (tree type, combined_fn fn)
   2083  1.1  mrg {
   2084  1.1  mrg   return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
   2085  1.1  mrg }
   2086  1.1  mrg 
   2087  1.1  mrg /* Like mathfn_built_in_1, but take a built_in_function and
   2088  1.1  mrg    always use the implicit array.  */
   2089  1.1  mrg 
   2090  1.1  mrg tree
   2091  1.1  mrg mathfn_built_in (tree type, enum built_in_function fn)
   2092  1.1  mrg {
   2093  1.1  mrg   return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
   2094  1.1  mrg }
   2095  1.1  mrg 
   2096  1.1  mrg /* Return the type associated with a built in function, i.e., the one
   2097  1.1  mrg    to be passed to mathfn_built_in to get the type-specific
   2098  1.1  mrg    function.  */
   2099  1.1  mrg 
   2100  1.1  mrg tree
   2101  1.1  mrg mathfn_built_in_type (combined_fn fn)
   2102  1.1  mrg {
   2103  1.1  mrg #define CASE_MATHFN(MATHFN)			\
   2104  1.1  mrg   case CFN_BUILT_IN_##MATHFN:			\
   2105  1.1  mrg     return double_type_node;			\
   2106  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F:		\
   2107  1.1  mrg     return float_type_node;			\
   2108  1.1  mrg   case CFN_BUILT_IN_##MATHFN##L:		\
   2109  1.1  mrg     return long_double_type_node;
   2110  1.1  mrg 
   2111  1.1  mrg #define CASE_MATHFN_FLOATN(MATHFN)		\
   2112  1.1  mrg   CASE_MATHFN(MATHFN)				\
   2113  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F16:		\
   2114  1.1  mrg     return float16_type_node;			\
   2115  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F32:		\
   2116  1.1  mrg     return float32_type_node;			\
   2117  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F64:		\
   2118  1.1  mrg     return float64_type_node;			\
   2119  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F128:		\
   2120  1.1  mrg     return float128_type_node;			\
   2121  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F32X:		\
   2122  1.1  mrg     return float32x_type_node;			\
   2123  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F64X:		\
   2124  1.1  mrg     return float64x_type_node;			\
   2125  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F128X:		\
   2126  1.1  mrg     return float128x_type_node;
   2127  1.1  mrg 
   2128  1.1  mrg /* Similar to above, but appends _R after any F/L suffix.  */
   2129  1.1  mrg #define CASE_MATHFN_REENT(MATHFN) \
   2130  1.1  mrg   case CFN_BUILT_IN_##MATHFN##_R:		\
   2131  1.1  mrg     return double_type_node;			\
   2132  1.1  mrg   case CFN_BUILT_IN_##MATHFN##F_R:		\
   2133  1.1  mrg     return float_type_node;			\
   2134  1.1  mrg   case CFN_BUILT_IN_##MATHFN##L_R:		\
   2135  1.1  mrg     return long_double_type_node;
   2136  1.1  mrg 
   2137  1.1  mrg   switch (fn)
   2138  1.1  mrg     {
   2139  1.1  mrg     SEQ_OF_CASE_MATHFN
   2140  1.1  mrg 
   2141  1.1  mrg     default:
   2142  1.1  mrg       return NULL_TREE;
   2143  1.1  mrg     }
   2144  1.1  mrg 
   2145  1.1  mrg #undef CASE_MATHFN
   2146  1.1  mrg #undef CASE_MATHFN_FLOATN
   2147  1.1  mrg #undef CASE_MATHFN_REENT
   2148  1.1  mrg #undef SEQ_OF_CASE_MATHFN
   2149  1.1  mrg }
   2150  1.1  mrg 
   2151  1.1  mrg /* Check whether there is an internal function associated with function FN
   2152  1.1  mrg    and return type RETURN_TYPE.  Return the function if so, otherwise return
   2153  1.1  mrg    IFN_LAST.
   2154  1.1  mrg 
   2155  1.1  mrg    Note that this function only tests whether the function is defined in
   2156  1.1  mrg    internals.def, not whether it is actually available on the target.  */
   2157  1.1  mrg 
   2158  1.1  mrg static internal_fn
   2159  1.1  mrg associated_internal_fn (built_in_function fn, tree return_type)
   2160  1.1  mrg {
   2161  1.1  mrg   switch (fn)
   2162  1.1  mrg     {
   2163  1.1  mrg #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
   2164  1.1  mrg     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
   2165  1.1  mrg #define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
   2166  1.1  mrg     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
   2167  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
   2168  1.1  mrg #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
   2169  1.1  mrg     CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
   2170  1.1  mrg #include "internal-fn.def"
   2171  1.1  mrg 
   2172  1.1  mrg     CASE_FLT_FN (BUILT_IN_POW10):
   2173  1.1  mrg       return IFN_EXP10;
   2174  1.1  mrg 
   2175  1.1  mrg     CASE_FLT_FN (BUILT_IN_DREM):
   2176  1.1  mrg       return IFN_REMAINDER;
   2177  1.1  mrg 
   2178  1.1  mrg     CASE_FLT_FN (BUILT_IN_SCALBN):
   2179  1.1  mrg     CASE_FLT_FN (BUILT_IN_SCALBLN):
   2180  1.1  mrg       if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
   2181  1.1  mrg 	return IFN_LDEXP;
   2182  1.1  mrg       return IFN_LAST;
   2183  1.1  mrg 
   2184  1.1  mrg     default:
   2185  1.1  mrg       return IFN_LAST;
   2186  1.1  mrg     }
   2187  1.1  mrg }
   2188  1.1  mrg 
   2189  1.1  mrg /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
   2190  1.1  mrg    return its code, otherwise return IFN_LAST.  Note that this function
   2191  1.1  mrg    only tests whether the function is defined in internals.def, not whether
   2192  1.1  mrg    it is actually available on the target.  */
   2193  1.1  mrg 
   2194  1.1  mrg internal_fn
   2195  1.1  mrg associated_internal_fn (tree fndecl)
   2196  1.1  mrg {
   2197  1.1  mrg   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
   2198  1.1  mrg   return associated_internal_fn (DECL_FUNCTION_CODE (fndecl),
   2199  1.1  mrg 				 TREE_TYPE (TREE_TYPE (fndecl)));
   2200  1.1  mrg }
   2201  1.1  mrg 
   2202  1.1  mrg /* Check whether there is an internal function associated with function CFN
   2203  1.1  mrg    and return type RETURN_TYPE.  Return the function if so, otherwise return
   2204  1.1  mrg    IFN_LAST.
   2205  1.1  mrg 
   2206  1.1  mrg    Note that this function only tests whether the function is defined in
   2207  1.1  mrg    internals.def, not whether it is actually available on the target.  */
   2208  1.1  mrg 
   2209  1.1  mrg internal_fn
   2210  1.1  mrg associated_internal_fn (combined_fn cfn, tree return_type)
   2211  1.1  mrg {
   2212  1.1  mrg   if (internal_fn_p (cfn))
   2213  1.1  mrg     return as_internal_fn (cfn);
   2214  1.1  mrg   return associated_internal_fn (as_builtin_fn (cfn), return_type);
   2215  1.1  mrg }
   2216  1.1  mrg 
   2217  1.1  mrg /* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
   2218  1.1  mrg    on the current target by a call to an internal function, return the
   2219  1.1  mrg    code of that internal function, otherwise return IFN_LAST.  The caller
   2220  1.1  mrg    is responsible for ensuring that any side-effects of the built-in
   2221  1.1  mrg    call are dealt with correctly.  E.g. if CALL sets errno, the caller
   2222  1.1  mrg    must decide that the errno result isn't needed or make it available
   2223  1.1  mrg    in some other way.  */
   2224  1.1  mrg 
   2225  1.1  mrg internal_fn
   2226  1.1  mrg replacement_internal_fn (gcall *call)
   2227  1.1  mrg {
   2228  1.1  mrg   if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
   2229  1.1  mrg     {
   2230  1.1  mrg       internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
   2231  1.1  mrg       if (ifn != IFN_LAST)
   2232  1.1  mrg 	{
   2233  1.1  mrg 	  tree_pair types = direct_internal_fn_types (ifn, call);
   2234  1.1  mrg 	  optimization_type opt_type = bb_optimization_type (gimple_bb (call));
   2235  1.1  mrg 	  if (direct_internal_fn_supported_p (ifn, types, opt_type))
   2236  1.1  mrg 	    return ifn;
   2237  1.1  mrg 	}
   2238  1.1  mrg     }
   2239  1.1  mrg   return IFN_LAST;
   2240  1.1  mrg }
   2241  1.1  mrg 
   2242  1.1  mrg /* Expand a call to the builtin trinary math functions (fma).
   2243  1.1  mrg    Return NULL_RTX if a normal call should be emitted rather than expanding the
   2244  1.1  mrg    function in-line.  EXP is the expression that is a call to the builtin
   2245  1.1  mrg    function; if convenient, the result should be placed in TARGET.
   2246  1.1  mrg    SUBTARGET may be used as the target for computing one of EXP's
   2247  1.1  mrg    operands.  */
   2248  1.1  mrg 
   2249  1.1  mrg static rtx
   2250  1.1  mrg expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
   2251  1.1  mrg {
   2252  1.1  mrg   optab builtin_optab;
   2253  1.1  mrg   rtx op0, op1, op2, result;
   2254  1.1  mrg   rtx_insn *insns;
   2255  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   2256  1.1  mrg   tree arg0, arg1, arg2;
   2257  1.1  mrg   machine_mode mode;
   2258  1.1  mrg 
   2259  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
   2260  1.1  mrg     return NULL_RTX;
   2261  1.1  mrg 
   2262  1.1  mrg   arg0 = CALL_EXPR_ARG (exp, 0);
   2263  1.1  mrg   arg1 = CALL_EXPR_ARG (exp, 1);
   2264  1.1  mrg   arg2 = CALL_EXPR_ARG (exp, 2);
   2265  1.1  mrg 
   2266  1.1  mrg   switch (DECL_FUNCTION_CODE (fndecl))
   2267  1.1  mrg     {
   2268  1.1  mrg     CASE_FLT_FN (BUILT_IN_FMA):
   2269  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
   2270  1.1  mrg       builtin_optab = fma_optab; break;
   2271  1.1  mrg     default:
   2272  1.1  mrg       gcc_unreachable ();
   2273  1.1  mrg     }
   2274  1.1  mrg 
   2275  1.1  mrg   /* Make a suitable register to place result in.  */
   2276  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (exp));
   2277  1.1  mrg 
   2278  1.1  mrg   /* Before working hard, check whether the instruction is available.  */
   2279  1.1  mrg   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
   2280  1.1  mrg     return NULL_RTX;
   2281  1.1  mrg 
   2282  1.1  mrg   result = gen_reg_rtx (mode);
   2283  1.1  mrg 
   2284  1.1  mrg   /* Always stabilize the argument list.  */
   2285  1.1  mrg   CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
   2286  1.1  mrg   CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
   2287  1.1  mrg   CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
   2288  1.1  mrg 
   2289  1.1  mrg   op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
   2290  1.1  mrg   op1 = expand_normal (arg1);
   2291  1.1  mrg   op2 = expand_normal (arg2);
   2292  1.1  mrg 
   2293  1.1  mrg   start_sequence ();
   2294  1.1  mrg 
   2295  1.1  mrg   /* Compute into RESULT.
   2296  1.1  mrg      Set RESULT to wherever the result comes back.  */
   2297  1.1  mrg   result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
   2298  1.1  mrg 			      result, 0);
   2299  1.1  mrg 
   2300  1.1  mrg   /* If we were unable to expand via the builtin, stop the sequence
   2301  1.1  mrg      (without outputting the insns) and call to the library function
   2302  1.1  mrg      with the stabilized argument list.  */
   2303  1.1  mrg   if (result == 0)
   2304  1.1  mrg     {
   2305  1.1  mrg       end_sequence ();
   2306  1.1  mrg       return expand_call (exp, target, target == const0_rtx);
   2307  1.1  mrg     }
   2308  1.1  mrg 
   2309  1.1  mrg   /* Output the entire sequence.  */
   2310  1.1  mrg   insns = get_insns ();
   2311  1.1  mrg   end_sequence ();
   2312  1.1  mrg   emit_insn (insns);
   2313  1.1  mrg 
   2314  1.1  mrg   return result;
   2315  1.1  mrg }
   2316  1.1  mrg 
   2317  1.1  mrg /* Expand a call to the builtin sin and cos math functions.
   2318  1.1  mrg    Return NULL_RTX if a normal call should be emitted rather than expanding the
   2319  1.1  mrg    function in-line.  EXP is the expression that is a call to the builtin
   2320  1.1  mrg    function; if convenient, the result should be placed in TARGET.
   2321  1.1  mrg    SUBTARGET may be used as the target for computing one of EXP's
   2322  1.1  mrg    operands.  */
   2323  1.1  mrg 
   2324  1.1  mrg static rtx
   2325  1.1  mrg expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   2326  1.1  mrg {
   2327  1.1  mrg   optab builtin_optab;
   2328  1.1  mrg   rtx op0;
   2329  1.1  mrg   rtx_insn *insns;
   2330  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   2331  1.1  mrg   machine_mode mode;
   2332  1.1  mrg   tree arg;
   2333  1.1  mrg 
   2334  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   2335  1.1  mrg     return NULL_RTX;
   2336  1.1  mrg 
   2337  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   2338  1.1  mrg 
   2339  1.1  mrg   switch (DECL_FUNCTION_CODE (fndecl))
   2340  1.1  mrg     {
   2341  1.1  mrg     CASE_FLT_FN (BUILT_IN_SIN):
   2342  1.1  mrg     CASE_FLT_FN (BUILT_IN_COS):
   2343  1.1  mrg       builtin_optab = sincos_optab; break;
   2344  1.1  mrg     default:
   2345  1.1  mrg       gcc_unreachable ();
   2346  1.1  mrg     }
   2347  1.1  mrg 
   2348  1.1  mrg   /* Make a suitable register to place result in.  */
   2349  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (exp));
   2350  1.1  mrg 
   2351  1.1  mrg   /* Check if sincos insn is available, otherwise fallback
   2352  1.1  mrg      to sin or cos insn.  */
   2353  1.1  mrg   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
   2354  1.1  mrg     switch (DECL_FUNCTION_CODE (fndecl))
   2355  1.1  mrg       {
   2356  1.1  mrg       CASE_FLT_FN (BUILT_IN_SIN):
   2357  1.1  mrg 	builtin_optab = sin_optab; break;
   2358  1.1  mrg       CASE_FLT_FN (BUILT_IN_COS):
   2359  1.1  mrg 	builtin_optab = cos_optab; break;
   2360  1.1  mrg       default:
   2361  1.1  mrg 	gcc_unreachable ();
   2362  1.1  mrg       }
   2363  1.1  mrg 
   2364  1.1  mrg   /* Before working hard, check whether the instruction is available.  */
   2365  1.1  mrg   if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
   2366  1.1  mrg     {
   2367  1.1  mrg       rtx result = gen_reg_rtx (mode);
   2368  1.1  mrg 
   2369  1.1  mrg       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
   2370  1.1  mrg 	 need to expand the argument again.  This way, we will not perform
   2371  1.1  mrg 	 side-effects more the once.  */
   2372  1.1  mrg       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
   2373  1.1  mrg 
   2374  1.1  mrg       op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
   2375  1.1  mrg 
   2376  1.1  mrg       start_sequence ();
   2377  1.1  mrg 
   2378  1.1  mrg       /* Compute into RESULT.
   2379  1.1  mrg 	 Set RESULT to wherever the result comes back.  */
   2380  1.1  mrg       if (builtin_optab == sincos_optab)
   2381  1.1  mrg 	{
   2382  1.1  mrg 	  int ok;
   2383  1.1  mrg 
   2384  1.1  mrg 	  switch (DECL_FUNCTION_CODE (fndecl))
   2385  1.1  mrg 	    {
   2386  1.1  mrg 	    CASE_FLT_FN (BUILT_IN_SIN):
   2387  1.1  mrg 	      ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
   2388  1.1  mrg 	      break;
   2389  1.1  mrg 	    CASE_FLT_FN (BUILT_IN_COS):
   2390  1.1  mrg 	      ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
   2391  1.1  mrg 	      break;
   2392  1.1  mrg 	    default:
   2393  1.1  mrg 	      gcc_unreachable ();
   2394  1.1  mrg 	    }
   2395  1.1  mrg 	  gcc_assert (ok);
   2396  1.1  mrg 	}
   2397  1.1  mrg       else
   2398  1.1  mrg 	result = expand_unop (mode, builtin_optab, op0, result, 0);
   2399  1.1  mrg 
   2400  1.1  mrg       if (result != 0)
   2401  1.1  mrg 	{
   2402  1.1  mrg 	  /* Output the entire sequence.  */
   2403  1.1  mrg 	  insns = get_insns ();
   2404  1.1  mrg 	  end_sequence ();
   2405  1.1  mrg 	  emit_insn (insns);
   2406  1.1  mrg 	  return result;
   2407  1.1  mrg 	}
   2408  1.1  mrg 
   2409  1.1  mrg       /* If we were unable to expand via the builtin, stop the sequence
   2410  1.1  mrg 	 (without outputting the insns) and call to the library function
   2411  1.1  mrg 	 with the stabilized argument list.  */
   2412  1.1  mrg       end_sequence ();
   2413  1.1  mrg     }
   2414  1.1  mrg 
   2415  1.1  mrg   return expand_call (exp, target, target == const0_rtx);
   2416  1.1  mrg }
   2417  1.1  mrg 
   2418  1.1  mrg /* Given an interclass math builtin decl FNDECL and it's argument ARG
   2419  1.1  mrg    return an RTL instruction code that implements the functionality.
   2420  1.1  mrg    If that isn't possible or available return CODE_FOR_nothing.  */
   2421  1.1  mrg 
   2422  1.1  mrg static enum insn_code
   2423  1.1  mrg interclass_mathfn_icode (tree arg, tree fndecl)
   2424  1.1  mrg {
   2425  1.1  mrg   bool errno_set = false;
   2426  1.1  mrg   optab builtin_optab = unknown_optab;
   2427  1.1  mrg   machine_mode mode;
   2428  1.1  mrg 
   2429  1.1  mrg   switch (DECL_FUNCTION_CODE (fndecl))
   2430  1.1  mrg     {
   2431  1.1  mrg     CASE_FLT_FN (BUILT_IN_ILOGB):
   2432  1.1  mrg       errno_set = true; builtin_optab = ilogb_optab; break;
   2433  1.1  mrg     CASE_FLT_FN (BUILT_IN_ISINF):
   2434  1.1  mrg       builtin_optab = isinf_optab; break;
   2435  1.1  mrg     case BUILT_IN_ISNORMAL:
   2436  1.1  mrg     case BUILT_IN_ISFINITE:
   2437  1.1  mrg     CASE_FLT_FN (BUILT_IN_FINITE):
   2438  1.1  mrg     case BUILT_IN_FINITED32:
   2439  1.1  mrg     case BUILT_IN_FINITED64:
   2440  1.1  mrg     case BUILT_IN_FINITED128:
   2441  1.1  mrg     case BUILT_IN_ISINFD32:
   2442  1.1  mrg     case BUILT_IN_ISINFD64:
   2443  1.1  mrg     case BUILT_IN_ISINFD128:
   2444  1.1  mrg       /* These builtins have no optabs (yet).  */
   2445  1.1  mrg       break;
   2446  1.1  mrg     default:
   2447  1.1  mrg       gcc_unreachable ();
   2448  1.1  mrg     }
   2449  1.1  mrg 
   2450  1.1  mrg   /* There's no easy way to detect the case we need to set EDOM.  */
   2451  1.1  mrg   if (flag_errno_math && errno_set)
   2452  1.1  mrg     return CODE_FOR_nothing;
   2453  1.1  mrg 
   2454  1.1  mrg   /* Optab mode depends on the mode of the input argument.  */
   2455  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (arg));
   2456  1.1  mrg 
   2457  1.1  mrg   if (builtin_optab)
   2458  1.1  mrg     return optab_handler (builtin_optab, mode);
   2459  1.1  mrg   return CODE_FOR_nothing;
   2460  1.1  mrg }
   2461  1.1  mrg 
   2462  1.1  mrg /* Expand a call to one of the builtin math functions that operate on
   2463  1.1  mrg    floating point argument and output an integer result (ilogb, isinf,
   2464  1.1  mrg    isnan, etc).
   2465  1.1  mrg    Return 0 if a normal call should be emitted rather than expanding the
   2466  1.1  mrg    function in-line.  EXP is the expression that is a call to the builtin
   2467  1.1  mrg    function; if convenient, the result should be placed in TARGET.  */
   2468  1.1  mrg 
   2469  1.1  mrg static rtx
   2470  1.1  mrg expand_builtin_interclass_mathfn (tree exp, rtx target)
   2471  1.1  mrg {
   2472  1.1  mrg   enum insn_code icode = CODE_FOR_nothing;
   2473  1.1  mrg   rtx op0;
   2474  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   2475  1.1  mrg   machine_mode mode;
   2476  1.1  mrg   tree arg;
   2477  1.1  mrg 
   2478  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   2479  1.1  mrg     return NULL_RTX;
   2480  1.1  mrg 
   2481  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   2482  1.1  mrg   icode = interclass_mathfn_icode (arg, fndecl);
   2483  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (arg));
   2484  1.1  mrg 
   2485  1.1  mrg   if (icode != CODE_FOR_nothing)
   2486  1.1  mrg     {
   2487  1.1  mrg       class expand_operand ops[1];
   2488  1.1  mrg       rtx_insn *last = get_last_insn ();
   2489  1.1  mrg       tree orig_arg = arg;
   2490  1.1  mrg 
   2491  1.1  mrg       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
   2492  1.1  mrg 	 need to expand the argument again.  This way, we will not perform
   2493  1.1  mrg 	 side-effects more the once.  */
   2494  1.1  mrg       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
   2495  1.1  mrg 
   2496  1.1  mrg       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
   2497  1.1  mrg 
   2498  1.1  mrg       if (mode != GET_MODE (op0))
   2499  1.1  mrg 	op0 = convert_to_mode (mode, op0, 0);
   2500  1.1  mrg 
   2501  1.1  mrg       create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
   2502  1.1  mrg       if (maybe_legitimize_operands (icode, 0, 1, ops)
   2503  1.1  mrg 	  && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
   2504  1.1  mrg 	return ops[0].value;
   2505  1.1  mrg 
   2506  1.1  mrg       delete_insns_since (last);
   2507  1.1  mrg       CALL_EXPR_ARG (exp, 0) = orig_arg;
   2508  1.1  mrg     }
   2509  1.1  mrg 
   2510  1.1  mrg   return NULL_RTX;
   2511  1.1  mrg }
   2512  1.1  mrg 
   2513  1.1  mrg /* Expand a call to the builtin sincos math function.
   2514  1.1  mrg    Return NULL_RTX if a normal call should be emitted rather than expanding the
   2515  1.1  mrg    function in-line.  EXP is the expression that is a call to the builtin
   2516  1.1  mrg    function.  */
   2517  1.1  mrg 
   2518  1.1  mrg static rtx
   2519  1.1  mrg expand_builtin_sincos (tree exp)
   2520  1.1  mrg {
   2521  1.1  mrg   rtx op0, op1, op2, target1, target2;
   2522  1.1  mrg   machine_mode mode;
   2523  1.1  mrg   tree arg, sinp, cosp;
   2524  1.1  mrg   int result;
   2525  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   2526  1.1  mrg   tree alias_type, alias_off;
   2527  1.1  mrg 
   2528  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE,
   2529  1.1  mrg  			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   2530  1.1  mrg     return NULL_RTX;
   2531  1.1  mrg 
   2532  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   2533  1.1  mrg   sinp = CALL_EXPR_ARG (exp, 1);
   2534  1.1  mrg   cosp = CALL_EXPR_ARG (exp, 2);
   2535  1.1  mrg 
   2536  1.1  mrg   /* Make a suitable register to place result in.  */
   2537  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (arg));
   2538  1.1  mrg 
   2539  1.1  mrg   /* Check if sincos insn is available, otherwise emit the call.  */
   2540  1.1  mrg   if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
   2541  1.1  mrg     return NULL_RTX;
   2542  1.1  mrg 
   2543  1.1  mrg   target1 = gen_reg_rtx (mode);
   2544  1.1  mrg   target2 = gen_reg_rtx (mode);
   2545  1.1  mrg 
   2546  1.1  mrg   op0 = expand_normal (arg);
   2547  1.1  mrg   alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
   2548  1.1  mrg   alias_off = build_int_cst (alias_type, 0);
   2549  1.1  mrg   op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
   2550  1.1  mrg 					sinp, alias_off));
   2551  1.1  mrg   op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
   2552  1.1  mrg 					cosp, alias_off));
   2553  1.1  mrg 
   2554  1.1  mrg   /* Compute into target1 and target2.
   2555  1.1  mrg      Set TARGET to wherever the result comes back.  */
   2556  1.1  mrg   result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
   2557  1.1  mrg   gcc_assert (result);
   2558  1.1  mrg 
   2559  1.1  mrg   /* Move target1 and target2 to the memory locations indicated
   2560  1.1  mrg      by op1 and op2.  */
   2561  1.1  mrg   emit_move_insn (op1, target1);
   2562  1.1  mrg   emit_move_insn (op2, target2);
   2563  1.1  mrg 
   2564  1.1  mrg   return const0_rtx;
   2565  1.1  mrg }
   2566  1.1  mrg 
   2567  1.1  mrg /* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the
   2568  1.1  mrg    result and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
   2569  1.1  mrg static rtx
   2570  1.1  mrg expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode)
   2571  1.1  mrg {
   2572  1.1  mrg   if (!validate_arglist (exp, VOID_TYPE))
   2573  1.1  mrg     return NULL_RTX;
   2574  1.1  mrg 
   2575  1.1  mrg   insn_code icode = direct_optab_handler (fegetround_optab, SImode);
   2576  1.1  mrg   if (icode == CODE_FOR_nothing)
   2577  1.1  mrg     return NULL_RTX;
   2578  1.1  mrg 
   2579  1.1  mrg   if (target == 0
   2580  1.1  mrg       || GET_MODE (target) != target_mode
   2581  1.1  mrg       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
   2582  1.1  mrg     target = gen_reg_rtx (target_mode);
   2583  1.1  mrg 
   2584  1.1  mrg   rtx pat = GEN_FCN (icode) (target);
   2585  1.1  mrg   if (!pat)
   2586  1.1  mrg     return NULL_RTX;
   2587  1.1  mrg   emit_insn (pat);
   2588  1.1  mrg 
   2589  1.1  mrg   return target;
   2590  1.1  mrg }
   2591  1.1  mrg 
   2592  1.1  mrg /* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99
   2593  1.1  mrg    fenv.h), returning the result and setting it in TARGET.  Otherwise return
   2594  1.1  mrg    NULL_RTX on failure.  */
   2595  1.1  mrg static rtx
   2596  1.1  mrg expand_builtin_feclear_feraise_except (tree exp, rtx target,
   2597  1.1  mrg 				       machine_mode target_mode, optab op_optab)
   2598  1.1  mrg {
   2599  1.1  mrg   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
   2600  1.1  mrg     return NULL_RTX;
   2601  1.1  mrg   rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   2602  1.1  mrg 
   2603  1.1  mrg   insn_code icode = direct_optab_handler (op_optab, SImode);
   2604  1.1  mrg   if (icode == CODE_FOR_nothing)
   2605  1.1  mrg     return NULL_RTX;
   2606  1.1  mrg 
   2607  1.1  mrg   if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0)))
   2608  1.1  mrg     return NULL_RTX;
   2609  1.1  mrg 
   2610  1.1  mrg   if (target == 0
   2611  1.1  mrg       || GET_MODE (target) != target_mode
   2612  1.1  mrg       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
   2613  1.1  mrg     target = gen_reg_rtx (target_mode);
   2614  1.1  mrg 
   2615  1.1  mrg   rtx pat = GEN_FCN (icode) (target, op0);
   2616  1.1  mrg   if (!pat)
   2617  1.1  mrg     return NULL_RTX;
   2618  1.1  mrg   emit_insn (pat);
   2619  1.1  mrg 
   2620  1.1  mrg   return target;
   2621  1.1  mrg }
   2622  1.1  mrg 
   2623  1.1  mrg /* Expand a call to the internal cexpi builtin to the sincos math function.
   2624  1.1  mrg    EXP is the expression that is a call to the builtin function; if convenient,
   2625  1.1  mrg    the result should be placed in TARGET.  */
   2626  1.1  mrg 
   2627  1.1  mrg static rtx
   2628  1.1  mrg expand_builtin_cexpi (tree exp, rtx target)
   2629  1.1  mrg {
   2630  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   2631  1.1  mrg   tree arg, type;
   2632  1.1  mrg   machine_mode mode;
   2633  1.1  mrg   rtx op0, op1, op2;
   2634  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   2635  1.1  mrg 
   2636  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   2637  1.1  mrg     return NULL_RTX;
   2638  1.1  mrg 
   2639  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   2640  1.1  mrg   type = TREE_TYPE (arg);
   2641  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (arg));
   2642  1.1  mrg 
   2643  1.1  mrg   /* Try expanding via a sincos optab, fall back to emitting a libcall
   2644  1.1  mrg      to sincos or cexp.  We are sure we have sincos or cexp because cexpi
   2645  1.1  mrg      is only generated from sincos, cexp or if we have either of them.  */
   2646  1.1  mrg   if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
   2647  1.1  mrg     {
   2648  1.1  mrg       op1 = gen_reg_rtx (mode);
   2649  1.1  mrg       op2 = gen_reg_rtx (mode);
   2650  1.1  mrg 
   2651  1.1  mrg       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
   2652  1.1  mrg 
   2653  1.1  mrg       /* Compute into op1 and op2.  */
   2654  1.1  mrg       expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
   2655  1.1  mrg     }
   2656  1.1  mrg   else if (targetm.libc_has_function (function_sincos, type))
   2657  1.1  mrg     {
   2658  1.1  mrg       tree call, fn = NULL_TREE;
   2659  1.1  mrg       tree top1, top2;
   2660  1.1  mrg       rtx op1a, op2a;
   2661  1.1  mrg 
   2662  1.1  mrg       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
   2663  1.1  mrg 	fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
   2664  1.1  mrg       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
   2665  1.1  mrg 	fn = builtin_decl_explicit (BUILT_IN_SINCOS);
   2666  1.1  mrg       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
   2667  1.1  mrg 	fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
   2668  1.1  mrg       else
   2669  1.1  mrg 	gcc_unreachable ();
   2670  1.1  mrg 
   2671  1.1  mrg       op1 = assign_temp (TREE_TYPE (arg), 1, 1);
   2672  1.1  mrg       op2 = assign_temp (TREE_TYPE (arg), 1, 1);
   2673  1.1  mrg       op1a = copy_addr_to_reg (XEXP (op1, 0));
   2674  1.1  mrg       op2a = copy_addr_to_reg (XEXP (op2, 0));
   2675  1.1  mrg       top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
   2676  1.1  mrg       top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
   2677  1.1  mrg 
   2678  1.1  mrg       /* Make sure not to fold the sincos call again.  */
   2679  1.1  mrg       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
   2680  1.1  mrg       expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
   2681  1.1  mrg 				      call, 3, arg, top1, top2));
   2682  1.1  mrg     }
   2683  1.1  mrg   else
   2684  1.1  mrg     {
   2685  1.1  mrg       tree call, fn = NULL_TREE, narg;
   2686  1.1  mrg       tree ctype = build_complex_type (type);
   2687  1.1  mrg 
   2688  1.1  mrg       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
   2689  1.1  mrg 	fn = builtin_decl_explicit (BUILT_IN_CEXPF);
   2690  1.1  mrg       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
   2691  1.1  mrg 	fn = builtin_decl_explicit (BUILT_IN_CEXP);
   2692  1.1  mrg       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
   2693  1.1  mrg 	fn = builtin_decl_explicit (BUILT_IN_CEXPL);
   2694  1.1  mrg       else
   2695  1.1  mrg 	gcc_unreachable ();
   2696  1.1  mrg 
   2697  1.1  mrg       /* If we don't have a decl for cexp create one.  This is the
   2698  1.1  mrg 	 friendliest fallback if the user calls __builtin_cexpi
   2699  1.1  mrg 	 without full target C99 function support.  */
   2700  1.1  mrg       if (fn == NULL_TREE)
   2701  1.1  mrg 	{
   2702  1.1  mrg 	  tree fntype;
   2703  1.1  mrg 	  const char *name = NULL;
   2704  1.1  mrg 
   2705  1.1  mrg 	  if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
   2706  1.1  mrg 	    name = "cexpf";
   2707  1.1  mrg 	  else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
   2708  1.1  mrg 	    name = "cexp";
   2709  1.1  mrg 	  else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
   2710  1.1  mrg 	    name = "cexpl";
   2711  1.1  mrg 
   2712  1.1  mrg 	  fntype = build_function_type_list (ctype, ctype, NULL_TREE);
   2713  1.1  mrg 	  fn = build_fn_decl (name, fntype);
   2714  1.1  mrg 	}
   2715  1.1  mrg 
   2716  1.1  mrg       narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
   2717  1.1  mrg 			  build_real (type, dconst0), arg);
   2718  1.1  mrg 
   2719  1.1  mrg       /* Make sure not to fold the cexp call again.  */
   2720  1.1  mrg       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
   2721  1.1  mrg       return expand_expr (build_call_nary (ctype, call, 1, narg),
   2722  1.1  mrg 			  target, VOIDmode, EXPAND_NORMAL);
   2723  1.1  mrg     }
   2724  1.1  mrg 
   2725  1.1  mrg   /* Now build the proper return type.  */
   2726  1.1  mrg   return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
   2727  1.1  mrg 			      make_tree (TREE_TYPE (arg), op2),
   2728  1.1  mrg 			      make_tree (TREE_TYPE (arg), op1)),
   2729  1.1  mrg 		      target, VOIDmode, EXPAND_NORMAL);
   2730  1.1  mrg }
   2731  1.1  mrg 
   2732  1.1  mrg /* Conveniently construct a function call expression.  FNDECL names the
   2733  1.1  mrg    function to be called, N is the number of arguments, and the "..."
   2734  1.1  mrg    parameters are the argument expressions.  Unlike build_call_exr
   2735  1.1  mrg    this doesn't fold the call, hence it will always return a CALL_EXPR.  */
   2736  1.1  mrg 
   2737  1.1  mrg static tree
   2738  1.1  mrg build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
   2739  1.1  mrg {
   2740  1.1  mrg   va_list ap;
   2741  1.1  mrg   tree fntype = TREE_TYPE (fndecl);
   2742  1.1  mrg   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
   2743  1.1  mrg 
   2744  1.1  mrg   va_start (ap, n);
   2745  1.1  mrg   fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
   2746  1.1  mrg   va_end (ap);
   2747  1.1  mrg   SET_EXPR_LOCATION (fn, loc);
   2748  1.1  mrg   return fn;
   2749  1.1  mrg }
   2750  1.1  mrg 
   2751  1.1  mrg /* Expand a call to one of the builtin rounding functions gcc defines
   2752  1.1  mrg    as an extension (lfloor and lceil).  As these are gcc extensions we
   2753  1.1  mrg    do not need to worry about setting errno to EDOM.
   2754  1.1  mrg    If expanding via optab fails, lower expression to (int)(floor(x)).
   2755  1.1  mrg    EXP is the expression that is a call to the builtin function;
   2756  1.1  mrg    if convenient, the result should be placed in TARGET.  */
   2757  1.1  mrg 
   2758  1.1  mrg static rtx
   2759  1.1  mrg expand_builtin_int_roundingfn (tree exp, rtx target)
   2760  1.1  mrg {
   2761  1.1  mrg   convert_optab builtin_optab;
   2762  1.1  mrg   rtx op0, tmp;
   2763  1.1  mrg   rtx_insn *insns;
   2764  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   2765  1.1  mrg   enum built_in_function fallback_fn;
   2766  1.1  mrg   tree fallback_fndecl;
   2767  1.1  mrg   machine_mode mode;
   2768  1.1  mrg   tree arg;
   2769  1.1  mrg 
   2770  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   2771  1.1  mrg     return NULL_RTX;
   2772  1.1  mrg 
   2773  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   2774  1.1  mrg 
   2775  1.1  mrg   switch (DECL_FUNCTION_CODE (fndecl))
   2776  1.1  mrg     {
   2777  1.1  mrg     CASE_FLT_FN (BUILT_IN_ICEIL):
   2778  1.1  mrg     CASE_FLT_FN (BUILT_IN_LCEIL):
   2779  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLCEIL):
   2780  1.1  mrg       builtin_optab = lceil_optab;
   2781  1.1  mrg       fallback_fn = BUILT_IN_CEIL;
   2782  1.1  mrg       break;
   2783  1.1  mrg 
   2784  1.1  mrg     CASE_FLT_FN (BUILT_IN_IFLOOR):
   2785  1.1  mrg     CASE_FLT_FN (BUILT_IN_LFLOOR):
   2786  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLFLOOR):
   2787  1.1  mrg       builtin_optab = lfloor_optab;
   2788  1.1  mrg       fallback_fn = BUILT_IN_FLOOR;
   2789  1.1  mrg       break;
   2790  1.1  mrg 
   2791  1.1  mrg     default:
   2792  1.1  mrg       gcc_unreachable ();
   2793  1.1  mrg     }
   2794  1.1  mrg 
   2795  1.1  mrg   /* Make a suitable register to place result in.  */
   2796  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (exp));
   2797  1.1  mrg 
   2798  1.1  mrg   target = gen_reg_rtx (mode);
   2799  1.1  mrg 
   2800  1.1  mrg   /* Wrap the computation of the argument in a SAVE_EXPR, as we may
   2801  1.1  mrg      need to expand the argument again.  This way, we will not perform
   2802  1.1  mrg      side-effects more the once.  */
   2803  1.1  mrg   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
   2804  1.1  mrg 
   2805  1.1  mrg   op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
   2806  1.1  mrg 
   2807  1.1  mrg   start_sequence ();
   2808  1.1  mrg 
   2809  1.1  mrg   /* Compute into TARGET.  */
   2810  1.1  mrg   if (expand_sfix_optab (target, op0, builtin_optab))
   2811  1.1  mrg     {
   2812  1.1  mrg       /* Output the entire sequence.  */
   2813  1.1  mrg       insns = get_insns ();
   2814  1.1  mrg       end_sequence ();
   2815  1.1  mrg       emit_insn (insns);
   2816  1.1  mrg       return target;
   2817  1.1  mrg     }
   2818  1.1  mrg 
   2819  1.1  mrg   /* If we were unable to expand via the builtin, stop the sequence
   2820  1.1  mrg      (without outputting the insns).  */
   2821  1.1  mrg   end_sequence ();
   2822  1.1  mrg 
   2823  1.1  mrg   /* Fall back to floating point rounding optab.  */
   2824  1.1  mrg   fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
   2825  1.1  mrg 
   2826  1.1  mrg   /* For non-C99 targets we may end up without a fallback fndecl here
   2827  1.1  mrg      if the user called __builtin_lfloor directly.  In this case emit
   2828  1.1  mrg      a call to the floor/ceil variants nevertheless.  This should result
   2829  1.1  mrg      in the best user experience for not full C99 targets.  */
   2830  1.1  mrg   if (fallback_fndecl == NULL_TREE)
   2831  1.1  mrg     {
   2832  1.1  mrg       tree fntype;
   2833  1.1  mrg       const char *name = NULL;
   2834  1.1  mrg 
   2835  1.1  mrg       switch (DECL_FUNCTION_CODE (fndecl))
   2836  1.1  mrg 	{
   2837  1.1  mrg 	case BUILT_IN_ICEIL:
   2838  1.1  mrg 	case BUILT_IN_LCEIL:
   2839  1.1  mrg 	case BUILT_IN_LLCEIL:
   2840  1.1  mrg 	  name = "ceil";
   2841  1.1  mrg 	  break;
   2842  1.1  mrg 	case BUILT_IN_ICEILF:
   2843  1.1  mrg 	case BUILT_IN_LCEILF:
   2844  1.1  mrg 	case BUILT_IN_LLCEILF:
   2845  1.1  mrg 	  name = "ceilf";
   2846  1.1  mrg 	  break;
   2847  1.1  mrg 	case BUILT_IN_ICEILL:
   2848  1.1  mrg 	case BUILT_IN_LCEILL:
   2849  1.1  mrg 	case BUILT_IN_LLCEILL:
   2850  1.1  mrg 	  name = "ceill";
   2851  1.1  mrg 	  break;
   2852  1.1  mrg 	case BUILT_IN_IFLOOR:
   2853  1.1  mrg 	case BUILT_IN_LFLOOR:
   2854  1.1  mrg 	case BUILT_IN_LLFLOOR:
   2855  1.1  mrg 	  name = "floor";
   2856  1.1  mrg 	  break;
   2857  1.1  mrg 	case BUILT_IN_IFLOORF:
   2858  1.1  mrg 	case BUILT_IN_LFLOORF:
   2859  1.1  mrg 	case BUILT_IN_LLFLOORF:
   2860  1.1  mrg 	  name = "floorf";
   2861  1.1  mrg 	  break;
   2862  1.1  mrg 	case BUILT_IN_IFLOORL:
   2863  1.1  mrg 	case BUILT_IN_LFLOORL:
   2864  1.1  mrg 	case BUILT_IN_LLFLOORL:
   2865  1.1  mrg 	  name = "floorl";
   2866  1.1  mrg 	  break;
   2867  1.1  mrg 	default:
   2868  1.1  mrg 	  gcc_unreachable ();
   2869  1.1  mrg 	}
   2870  1.1  mrg 
   2871  1.1  mrg       fntype = build_function_type_list (TREE_TYPE (arg),
   2872  1.1  mrg 					 TREE_TYPE (arg), NULL_TREE);
   2873  1.1  mrg       fallback_fndecl = build_fn_decl (name, fntype);
   2874  1.1  mrg     }
   2875  1.1  mrg 
   2876  1.1  mrg   exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
   2877  1.1  mrg 
   2878  1.1  mrg   tmp = expand_normal (exp);
   2879  1.1  mrg   tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
   2880  1.1  mrg 
   2881  1.1  mrg   /* Truncate the result of floating point optab to integer
   2882  1.1  mrg      via expand_fix ().  */
   2883  1.1  mrg   target = gen_reg_rtx (mode);
   2884  1.1  mrg   expand_fix (target, tmp, 0);
   2885  1.1  mrg 
   2886  1.1  mrg   return target;
   2887  1.1  mrg }
   2888  1.1  mrg 
   2889  1.1  mrg /* Expand a call to one of the builtin math functions doing integer
   2890  1.1  mrg    conversion (lrint).
   2891  1.1  mrg    Return 0 if a normal call should be emitted rather than expanding the
   2892  1.1  mrg    function in-line.  EXP is the expression that is a call to the builtin
   2893  1.1  mrg    function; if convenient, the result should be placed in TARGET.  */
   2894  1.1  mrg 
   2895  1.1  mrg static rtx
   2896  1.1  mrg expand_builtin_int_roundingfn_2 (tree exp, rtx target)
   2897  1.1  mrg {
   2898  1.1  mrg   convert_optab builtin_optab;
   2899  1.1  mrg   rtx op0;
   2900  1.1  mrg   rtx_insn *insns;
   2901  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   2902  1.1  mrg   tree arg;
   2903  1.1  mrg   machine_mode mode;
   2904  1.1  mrg   enum built_in_function fallback_fn = BUILT_IN_NONE;
   2905  1.1  mrg 
   2906  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   2907  1.1  mrg     return NULL_RTX;
   2908  1.1  mrg 
   2909  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   2910  1.1  mrg 
   2911  1.1  mrg   switch (DECL_FUNCTION_CODE (fndecl))
   2912  1.1  mrg     {
   2913  1.1  mrg     CASE_FLT_FN (BUILT_IN_IRINT):
   2914  1.1  mrg       fallback_fn = BUILT_IN_LRINT;
   2915  1.1  mrg       gcc_fallthrough ();
   2916  1.1  mrg     CASE_FLT_FN (BUILT_IN_LRINT):
   2917  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLRINT):
   2918  1.1  mrg       builtin_optab = lrint_optab;
   2919  1.1  mrg       break;
   2920  1.1  mrg 
   2921  1.1  mrg     CASE_FLT_FN (BUILT_IN_IROUND):
   2922  1.1  mrg       fallback_fn = BUILT_IN_LROUND;
   2923  1.1  mrg       gcc_fallthrough ();
   2924  1.1  mrg     CASE_FLT_FN (BUILT_IN_LROUND):
   2925  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLROUND):
   2926  1.1  mrg       builtin_optab = lround_optab;
   2927  1.1  mrg       break;
   2928  1.1  mrg 
   2929  1.1  mrg     default:
   2930  1.1  mrg       gcc_unreachable ();
   2931  1.1  mrg     }
   2932  1.1  mrg 
   2933  1.1  mrg   /* There's no easy way to detect the case we need to set EDOM.  */
   2934  1.1  mrg   if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
   2935  1.1  mrg     return NULL_RTX;
   2936  1.1  mrg 
   2937  1.1  mrg   /* Make a suitable register to place result in.  */
   2938  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (exp));
   2939  1.1  mrg 
   2940  1.1  mrg   /* There's no easy way to detect the case we need to set EDOM.  */
   2941  1.1  mrg   if (!flag_errno_math)
   2942  1.1  mrg     {
   2943  1.1  mrg       rtx result = gen_reg_rtx (mode);
   2944  1.1  mrg 
   2945  1.1  mrg       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
   2946  1.1  mrg 	 need to expand the argument again.  This way, we will not perform
   2947  1.1  mrg 	 side-effects more the once.  */
   2948  1.1  mrg       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
   2949  1.1  mrg 
   2950  1.1  mrg       op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
   2951  1.1  mrg 
   2952  1.1  mrg       start_sequence ();
   2953  1.1  mrg 
   2954  1.1  mrg       if (expand_sfix_optab (result, op0, builtin_optab))
   2955  1.1  mrg 	{
   2956  1.1  mrg 	  /* Output the entire sequence.  */
   2957  1.1  mrg 	  insns = get_insns ();
   2958  1.1  mrg 	  end_sequence ();
   2959  1.1  mrg 	  emit_insn (insns);
   2960  1.1  mrg 	  return result;
   2961  1.1  mrg 	}
   2962  1.1  mrg 
   2963  1.1  mrg       /* If we were unable to expand via the builtin, stop the sequence
   2964  1.1  mrg 	 (without outputting the insns) and call to the library function
   2965  1.1  mrg 	 with the stabilized argument list.  */
   2966  1.1  mrg       end_sequence ();
   2967  1.1  mrg     }
   2968  1.1  mrg 
   2969  1.1  mrg   if (fallback_fn != BUILT_IN_NONE)
   2970  1.1  mrg     {
   2971  1.1  mrg       /* Fall back to rounding to long int.  Use implicit_p 0 - for non-C99
   2972  1.1  mrg 	 targets, (int) round (x) should never be transformed into
   2973  1.1  mrg 	 BUILT_IN_IROUND and if __builtin_iround is called directly, emit
   2974  1.1  mrg 	 a call to lround in the hope that the target provides at least some
   2975  1.1  mrg 	 C99 functions.  This should result in the best user experience for
   2976  1.1  mrg 	 not full C99 targets.
   2977  1.1  mrg 	 As scalar float conversions with same mode are useless in GIMPLE,
   2978  1.1  mrg 	 we can end up e.g. with _Float32 argument passed to float builtin,
   2979  1.1  mrg 	 try to get the type from the builtin prototype first.  */
   2980  1.1  mrg       tree fallback_fndecl = NULL_TREE;
   2981  1.1  mrg       if (tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
   2982  1.1  mrg         fallback_fndecl
   2983  1.1  mrg           = mathfn_built_in_1 (TREE_VALUE (argtypes),
   2984  1.1  mrg 			       as_combined_fn (fallback_fn), 0);
   2985  1.1  mrg       if (fallback_fndecl == NULL_TREE)
   2986  1.1  mrg 	fallback_fndecl
   2987  1.1  mrg 	  = mathfn_built_in_1 (TREE_TYPE (arg),
   2988  1.1  mrg 			       as_combined_fn (fallback_fn), 0);
   2989  1.1  mrg       if (fallback_fndecl)
   2990  1.1  mrg 	{
   2991  1.1  mrg 	  exp = build_call_nofold_loc (EXPR_LOCATION (exp),
   2992  1.1  mrg 				       fallback_fndecl, 1, arg);
   2993  1.1  mrg 
   2994  1.1  mrg 	  target = expand_call (exp, NULL_RTX, target == const0_rtx);
   2995  1.1  mrg 	  target = maybe_emit_group_store (target, TREE_TYPE (exp));
   2996  1.1  mrg 	  return convert_to_mode (mode, target, 0);
   2997  1.1  mrg 	}
   2998  1.1  mrg     }
   2999  1.1  mrg 
   3000  1.1  mrg   return expand_call (exp, target, target == const0_rtx);
   3001  1.1  mrg }
   3002  1.1  mrg 
   3003  1.1  mrg /* Expand a call to the powi built-in mathematical function.  Return NULL_RTX if
   3004  1.1  mrg    a normal call should be emitted rather than expanding the function
   3005  1.1  mrg    in-line.  EXP is the expression that is a call to the builtin
   3006  1.1  mrg    function; if convenient, the result should be placed in TARGET.  */
   3007  1.1  mrg 
   3008  1.1  mrg static rtx
   3009  1.1  mrg expand_builtin_powi (tree exp, rtx target)
   3010  1.1  mrg {
   3011  1.1  mrg   tree arg0, arg1;
   3012  1.1  mrg   rtx op0, op1;
   3013  1.1  mrg   machine_mode mode;
   3014  1.1  mrg   machine_mode mode2;
   3015  1.1  mrg 
   3016  1.1  mrg   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
   3017  1.1  mrg     return NULL_RTX;
   3018  1.1  mrg 
   3019  1.1  mrg   arg0 = CALL_EXPR_ARG (exp, 0);
   3020  1.1  mrg   arg1 = CALL_EXPR_ARG (exp, 1);
   3021  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (exp));
   3022  1.1  mrg 
   3023  1.1  mrg   /* Emit a libcall to libgcc.  */
   3024  1.1  mrg 
   3025  1.1  mrg   /* Mode of the 2nd argument must match that of an int.  */
   3026  1.1  mrg   mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
   3027  1.1  mrg 
   3028  1.1  mrg   if (target == NULL_RTX)
   3029  1.1  mrg     target = gen_reg_rtx (mode);
   3030  1.1  mrg 
   3031  1.1  mrg   op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
   3032  1.1  mrg   if (GET_MODE (op0) != mode)
   3033  1.1  mrg     op0 = convert_to_mode (mode, op0, 0);
   3034  1.1  mrg   op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
   3035  1.1  mrg   if (GET_MODE (op1) != mode2)
   3036  1.1  mrg     op1 = convert_to_mode (mode2, op1, 0);
   3037  1.1  mrg 
   3038  1.1  mrg   target = emit_library_call_value (optab_libfunc (powi_optab, mode),
   3039  1.1  mrg 				    target, LCT_CONST, mode,
   3040  1.1  mrg 				    op0, mode, op1, mode2);
   3041  1.1  mrg 
   3042  1.1  mrg   return target;
   3043  1.1  mrg }
   3044  1.1  mrg 
   3045  1.1  mrg /* Expand expression EXP which is a call to the strlen builtin.  Return
   3046  1.1  mrg    NULL_RTX if we failed and the caller should emit a normal call, otherwise
   3047  1.1  mrg    try to get the result in TARGET, if convenient.  */
   3048  1.1  mrg 
   3049  1.1  mrg static rtx
   3050  1.1  mrg expand_builtin_strlen (tree exp, rtx target,
   3051  1.1  mrg 		       machine_mode target_mode)
   3052  1.1  mrg {
   3053  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   3054  1.1  mrg     return NULL_RTX;
   3055  1.1  mrg 
   3056  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 0);
   3057  1.1  mrg 
   3058  1.1  mrg   /* If the length can be computed at compile-time, return it.  */
   3059  1.1  mrg   if (tree len = c_strlen (src, 0))
   3060  1.1  mrg     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
   3061  1.1  mrg 
   3062  1.1  mrg   /* If the length can be computed at compile-time and is constant
   3063  1.1  mrg      integer, but there are side-effects in src, evaluate
   3064  1.1  mrg      src for side-effects, then return len.
   3065  1.1  mrg      E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
   3066  1.1  mrg      can be optimized into: i++; x = 3;  */
   3067  1.1  mrg   tree len = c_strlen (src, 1);
   3068  1.1  mrg   if (len && TREE_CODE (len) == INTEGER_CST)
   3069  1.1  mrg     {
   3070  1.1  mrg       expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
   3071  1.1  mrg       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
   3072  1.1  mrg     }
   3073  1.1  mrg 
   3074  1.1  mrg   unsigned int align = get_pointer_alignment (src) / BITS_PER_UNIT;
   3075  1.1  mrg 
   3076  1.1  mrg   /* If SRC is not a pointer type, don't do this operation inline.  */
   3077  1.1  mrg   if (align == 0)
   3078  1.1  mrg     return NULL_RTX;
   3079  1.1  mrg 
   3080  1.1  mrg   /* Bail out if we can't compute strlen in the right mode.  */
   3081  1.1  mrg   machine_mode insn_mode;
   3082  1.1  mrg   enum insn_code icode = CODE_FOR_nothing;
   3083  1.1  mrg   FOR_EACH_MODE_FROM (insn_mode, target_mode)
   3084  1.1  mrg     {
   3085  1.1  mrg       icode = optab_handler (strlen_optab, insn_mode);
   3086  1.1  mrg       if (icode != CODE_FOR_nothing)
   3087  1.1  mrg 	break;
   3088  1.1  mrg     }
   3089  1.1  mrg   if (insn_mode == VOIDmode)
   3090  1.1  mrg     return NULL_RTX;
   3091  1.1  mrg 
   3092  1.1  mrg   /* Make a place to hold the source address.  We will not expand
   3093  1.1  mrg      the actual source until we are sure that the expansion will
   3094  1.1  mrg      not fail -- there are trees that cannot be expanded twice.  */
   3095  1.1  mrg   rtx src_reg = gen_reg_rtx (Pmode);
   3096  1.1  mrg 
   3097  1.1  mrg   /* Mark the beginning of the strlen sequence so we can emit the
   3098  1.1  mrg      source operand later.  */
   3099  1.1  mrg   rtx_insn *before_strlen = get_last_insn ();
   3100  1.1  mrg 
   3101  1.1  mrg   class expand_operand ops[4];
   3102  1.1  mrg   create_output_operand (&ops[0], target, insn_mode);
   3103  1.1  mrg   create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
   3104  1.1  mrg   create_integer_operand (&ops[2], 0);
   3105  1.1  mrg   create_integer_operand (&ops[3], align);
   3106  1.1  mrg   if (!maybe_expand_insn (icode, 4, ops))
   3107  1.1  mrg     return NULL_RTX;
   3108  1.1  mrg 
   3109  1.1  mrg   /* Check to see if the argument was declared attribute nonstring
   3110  1.1  mrg      and if so, issue a warning since at this point it's not known
   3111  1.1  mrg      to be nul-terminated.  */
   3112  1.1  mrg   maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
   3113  1.1  mrg 
   3114  1.1  mrg   /* Now that we are assured of success, expand the source.  */
   3115  1.1  mrg   start_sequence ();
   3116  1.1  mrg   rtx pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
   3117  1.1  mrg   if (pat != src_reg)
   3118  1.1  mrg     {
   3119  1.1  mrg #ifdef POINTERS_EXTEND_UNSIGNED
   3120  1.1  mrg       if (GET_MODE (pat) != Pmode)
   3121  1.1  mrg 	pat = convert_to_mode (Pmode, pat,
   3122  1.1  mrg 			       POINTERS_EXTEND_UNSIGNED);
   3123  1.1  mrg #endif
   3124  1.1  mrg       emit_move_insn (src_reg, pat);
   3125  1.1  mrg     }
   3126  1.1  mrg   pat = get_insns ();
   3127  1.1  mrg   end_sequence ();
   3128  1.1  mrg 
   3129  1.1  mrg   if (before_strlen)
   3130  1.1  mrg     emit_insn_after (pat, before_strlen);
   3131  1.1  mrg   else
   3132  1.1  mrg     emit_insn_before (pat, get_insns ());
   3133  1.1  mrg 
   3134  1.1  mrg   /* Return the value in the proper mode for this function.  */
   3135  1.1  mrg   if (GET_MODE (ops[0].value) == target_mode)
   3136  1.1  mrg     target = ops[0].value;
   3137  1.1  mrg   else if (target != 0)
   3138  1.1  mrg     convert_move (target, ops[0].value, 0);
   3139  1.1  mrg   else
   3140  1.1  mrg     target = convert_to_mode (target_mode, ops[0].value, 0);
   3141  1.1  mrg 
   3142  1.1  mrg   return target;
   3143  1.1  mrg }
   3144  1.1  mrg 
   3145  1.1  mrg /* Expand call EXP to the strnlen built-in, returning the result
   3146  1.1  mrg    and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
   3147  1.1  mrg 
   3148  1.1  mrg static rtx
   3149  1.1  mrg expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
   3150  1.1  mrg {
   3151  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   3152  1.1  mrg     return NULL_RTX;
   3153  1.1  mrg 
   3154  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 0);
   3155  1.1  mrg   tree bound = CALL_EXPR_ARG (exp, 1);
   3156  1.1  mrg 
   3157  1.1  mrg   if (!bound)
   3158  1.1  mrg     return NULL_RTX;
   3159  1.1  mrg 
   3160  1.1  mrg   location_t loc = UNKNOWN_LOCATION;
   3161  1.1  mrg   if (EXPR_HAS_LOCATION (exp))
   3162  1.1  mrg     loc = EXPR_LOCATION (exp);
   3163  1.1  mrg 
   3164  1.1  mrg   /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
   3165  1.1  mrg      so these conversions aren't necessary.  */
   3166  1.1  mrg   c_strlen_data lendata = { };
   3167  1.1  mrg   tree len = c_strlen (src, 0, &lendata, 1);
   3168  1.1  mrg   if (len)
   3169  1.1  mrg     len = fold_convert_loc (loc, TREE_TYPE (bound), len);
   3170  1.1  mrg 
   3171  1.1  mrg   if (TREE_CODE (bound) == INTEGER_CST)
   3172  1.1  mrg     {
   3173  1.1  mrg       if (!len)
   3174  1.1  mrg 	return NULL_RTX;
   3175  1.1  mrg 
   3176  1.1  mrg       len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
   3177  1.1  mrg       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
   3178  1.1  mrg     }
   3179  1.1  mrg 
   3180  1.1  mrg   if (TREE_CODE (bound) != SSA_NAME)
   3181  1.1  mrg     return NULL_RTX;
   3182  1.1  mrg 
   3183  1.1  mrg   wide_int min, max;
   3184  1.1  mrg   value_range r;
   3185  1.1  mrg   get_global_range_query ()->range_of_expr (r, bound);
   3186  1.1  mrg   if (r.kind () != VR_RANGE)
   3187  1.1  mrg     return NULL_RTX;
   3188  1.1  mrg   min = r.lower_bound ();
   3189  1.1  mrg   max = r.upper_bound ();
   3190  1.1  mrg 
   3191  1.1  mrg   if (!len || TREE_CODE (len) != INTEGER_CST)
   3192  1.1  mrg     {
   3193  1.1  mrg       bool exact;
   3194  1.1  mrg       lendata.decl = unterminated_array (src, &len, &exact);
   3195  1.1  mrg       if (!lendata.decl)
   3196  1.1  mrg 	return NULL_RTX;
   3197  1.1  mrg     }
   3198  1.1  mrg 
   3199  1.1  mrg   if (lendata.decl)
   3200  1.1  mrg     return NULL_RTX;
   3201  1.1  mrg 
   3202  1.1  mrg   if (wi::gtu_p (min, wi::to_wide (len)))
   3203  1.1  mrg     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
   3204  1.1  mrg 
   3205  1.1  mrg   len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
   3206  1.1  mrg   return expand_expr (len, target, target_mode, EXPAND_NORMAL);
   3207  1.1  mrg }
   3208  1.1  mrg 
   3209  1.1  mrg /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
   3210  1.1  mrg    bytes from bytes at DATA + OFFSET and return it reinterpreted as
   3211  1.1  mrg    a target constant.  */
   3212  1.1  mrg 
   3213  1.1  mrg static rtx
   3214  1.1  mrg builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset,
   3215  1.1  mrg 			 fixed_size_mode mode)
   3216  1.1  mrg {
   3217  1.1  mrg   /* The REPresentation pointed to by DATA need not be a nul-terminated
   3218  1.1  mrg      string but the caller guarantees it's large enough for MODE.  */
   3219  1.1  mrg   const char *rep = (const char *) data;
   3220  1.1  mrg 
   3221  1.1  mrg   /* The by-pieces infrastructure does not try to pick a vector mode
   3222  1.1  mrg      for memcpy expansion.  */
   3223  1.1  mrg   return c_readstr (rep + offset, as_a <scalar_int_mode> (mode),
   3224  1.1  mrg 		    /*nul_terminated=*/false);
   3225  1.1  mrg }
   3226  1.1  mrg 
   3227  1.1  mrg /* LEN specify length of the block of memcpy/memset operation.
   3228  1.1  mrg    Figure out its range and put it into MIN_SIZE/MAX_SIZE.
   3229  1.1  mrg    In some cases we can make very likely guess on max size, then we
   3230  1.1  mrg    set it into PROBABLE_MAX_SIZE.  */
   3231  1.1  mrg 
   3232  1.1  mrg static void
   3233  1.1  mrg determine_block_size (tree len, rtx len_rtx,
   3234  1.1  mrg 		      unsigned HOST_WIDE_INT *min_size,
   3235  1.1  mrg 		      unsigned HOST_WIDE_INT *max_size,
   3236  1.1  mrg 		      unsigned HOST_WIDE_INT *probable_max_size)
   3237  1.1  mrg {
   3238  1.1  mrg   if (CONST_INT_P (len_rtx))
   3239  1.1  mrg     {
   3240  1.1  mrg       *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
   3241  1.1  mrg       return;
   3242  1.1  mrg     }
   3243  1.1  mrg   else
   3244  1.1  mrg     {
   3245  1.1  mrg       wide_int min, max;
   3246  1.1  mrg       enum value_range_kind range_type = VR_UNDEFINED;
   3247  1.1  mrg 
   3248  1.1  mrg       /* Determine bounds from the type.  */
   3249  1.1  mrg       if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
   3250  1.1  mrg 	*min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
   3251  1.1  mrg       else
   3252  1.1  mrg 	*min_size = 0;
   3253  1.1  mrg       if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
   3254  1.1  mrg 	*probable_max_size = *max_size
   3255  1.1  mrg 	  = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
   3256  1.1  mrg       else
   3257  1.1  mrg 	*probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
   3258  1.1  mrg 
   3259  1.1  mrg       if (TREE_CODE (len) == SSA_NAME)
   3260  1.1  mrg 	{
   3261  1.1  mrg 	  value_range r;
   3262  1.1  mrg 	  get_global_range_query ()->range_of_expr (r, len);
   3263  1.1  mrg 	  range_type = r.kind ();
   3264  1.1  mrg 	  if (range_type != VR_UNDEFINED)
   3265  1.1  mrg 	    {
   3266  1.1  mrg 	      min = wi::to_wide (r.min ());
   3267  1.1  mrg 	      max = wi::to_wide (r.max ());
   3268  1.1  mrg 	    }
   3269  1.1  mrg 	}
   3270  1.1  mrg       if (range_type == VR_RANGE)
   3271  1.1  mrg 	{
   3272  1.1  mrg 	  if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
   3273  1.1  mrg 	    *min_size = min.to_uhwi ();
   3274  1.1  mrg 	  if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
   3275  1.1  mrg 	    *probable_max_size = *max_size = max.to_uhwi ();
   3276  1.1  mrg 	}
   3277  1.1  mrg       else if (range_type == VR_ANTI_RANGE)
   3278  1.1  mrg 	{
   3279  1.1  mrg 	  /* Code like
   3280  1.1  mrg 
   3281  1.1  mrg 	     int n;
   3282  1.1  mrg 	     if (n < 100)
   3283  1.1  mrg 	       memcpy (a, b, n)
   3284  1.1  mrg 
   3285  1.1  mrg 	     Produce anti range allowing negative values of N.  We still
   3286  1.1  mrg 	     can use the information and make a guess that N is not negative.
   3287  1.1  mrg 	     */
   3288  1.1  mrg 	  if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
   3289  1.1  mrg 	    *probable_max_size = min.to_uhwi () - 1;
   3290  1.1  mrg 	}
   3291  1.1  mrg     }
   3292  1.1  mrg   gcc_checking_assert (*max_size <=
   3293  1.1  mrg 		       (unsigned HOST_WIDE_INT)
   3294  1.1  mrg 			  GET_MODE_MASK (GET_MODE (len_rtx)));
   3295  1.1  mrg }
   3296  1.1  mrg 
   3297  1.1  mrg /* Expand a call EXP to the memcpy builtin.
   3298  1.1  mrg    Return NULL_RTX if we failed, the caller should emit a normal call,
   3299  1.1  mrg    otherwise try to get the result in TARGET, if convenient (and in
   3300  1.1  mrg    mode MODE if that's convenient).  */
   3301  1.1  mrg 
   3302  1.1  mrg static rtx
   3303  1.1  mrg expand_builtin_memcpy (tree exp, rtx target)
   3304  1.1  mrg {
   3305  1.1  mrg   if (!validate_arglist (exp,
   3306  1.1  mrg  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   3307  1.1  mrg     return NULL_RTX;
   3308  1.1  mrg 
   3309  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3310  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   3311  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   3312  1.1  mrg 
   3313  1.1  mrg   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
   3314  1.1  mrg 					  /*retmode=*/ RETURN_BEGIN, false);
   3315  1.1  mrg }
   3316  1.1  mrg 
   3317  1.1  mrg /* Check a call EXP to the memmove built-in for validity.
   3318  1.1  mrg    Return NULL_RTX on both success and failure.  */
   3319  1.1  mrg 
   3320  1.1  mrg static rtx
   3321  1.1  mrg expand_builtin_memmove (tree exp, rtx target)
   3322  1.1  mrg {
   3323  1.1  mrg   if (!validate_arglist (exp,
   3324  1.1  mrg  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   3325  1.1  mrg     return NULL_RTX;
   3326  1.1  mrg 
   3327  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3328  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   3329  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   3330  1.1  mrg 
   3331  1.1  mrg   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
   3332  1.1  mrg 					  /*retmode=*/ RETURN_BEGIN, true);
   3333  1.1  mrg }
   3334  1.1  mrg 
   3335  1.1  mrg /* Expand a call EXP to the mempcpy builtin.
   3336  1.1  mrg    Return NULL_RTX if we failed; the caller should emit a normal call,
   3337  1.1  mrg    otherwise try to get the result in TARGET, if convenient (and in
   3338  1.1  mrg    mode MODE if that's convenient).  */
   3339  1.1  mrg 
   3340  1.1  mrg static rtx
   3341  1.1  mrg expand_builtin_mempcpy (tree exp, rtx target)
   3342  1.1  mrg {
   3343  1.1  mrg   if (!validate_arglist (exp,
   3344  1.1  mrg  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   3345  1.1  mrg     return NULL_RTX;
   3346  1.1  mrg 
   3347  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3348  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   3349  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   3350  1.1  mrg 
   3351  1.1  mrg   /* Policy does not generally allow using compute_objsize (which
   3352  1.1  mrg      is used internally by check_memop_size) to change code generation
   3353  1.1  mrg      or drive optimization decisions.
   3354  1.1  mrg 
   3355  1.1  mrg      In this instance it is safe because the code we generate has
   3356  1.1  mrg      the same semantics regardless of the return value of
   3357  1.1  mrg      check_memop_sizes.   Exactly the same amount of data is copied
   3358  1.1  mrg      and the return value is exactly the same in both cases.
   3359  1.1  mrg 
   3360  1.1  mrg      Furthermore, check_memop_size always uses mode 0 for the call to
   3361  1.1  mrg      compute_objsize, so the imprecise nature of compute_objsize is
   3362  1.1  mrg      avoided.  */
   3363  1.1  mrg 
   3364  1.1  mrg   /* Avoid expanding mempcpy into memcpy when the call is determined
   3365  1.1  mrg      to overflow the buffer.  This also prevents the same overflow
   3366  1.1  mrg      from being diagnosed again when expanding memcpy.  */
   3367  1.1  mrg 
   3368  1.1  mrg   return expand_builtin_mempcpy_args (dest, src, len,
   3369  1.1  mrg 				      target, exp, /*retmode=*/ RETURN_END);
   3370  1.1  mrg }
   3371  1.1  mrg 
   3372  1.1  mrg /* Helper function to do the actual work for expand of memory copy family
   3373  1.1  mrg    functions (memcpy, mempcpy, stpcpy).  Expansing should assign LEN bytes
   3374  1.1  mrg    of memory from SRC to DEST and assign to TARGET if convenient.  Return
   3375  1.1  mrg    value is based on RETMODE argument.  */
   3376  1.1  mrg 
   3377  1.1  mrg static rtx
   3378  1.1  mrg expand_builtin_memory_copy_args (tree dest, tree src, tree len,
   3379  1.1  mrg 				 rtx target, tree exp, memop_ret retmode,
   3380  1.1  mrg 				 bool might_overlap)
   3381  1.1  mrg {
   3382  1.1  mrg   unsigned int src_align = get_pointer_alignment (src);
   3383  1.1  mrg   unsigned int dest_align = get_pointer_alignment (dest);
   3384  1.1  mrg   rtx dest_mem, src_mem, dest_addr, len_rtx;
   3385  1.1  mrg   HOST_WIDE_INT expected_size = -1;
   3386  1.1  mrg   unsigned int expected_align = 0;
   3387  1.1  mrg   unsigned HOST_WIDE_INT min_size;
   3388  1.1  mrg   unsigned HOST_WIDE_INT max_size;
   3389  1.1  mrg   unsigned HOST_WIDE_INT probable_max_size;
   3390  1.1  mrg 
   3391  1.1  mrg   bool is_move_done;
   3392  1.1  mrg 
   3393  1.1  mrg   /* If DEST is not a pointer type, call the normal function.  */
   3394  1.1  mrg   if (dest_align == 0)
   3395  1.1  mrg     return NULL_RTX;
   3396  1.1  mrg 
   3397  1.1  mrg   /* If either SRC is not a pointer type, don't do this
   3398  1.1  mrg      operation in-line.  */
   3399  1.1  mrg   if (src_align == 0)
   3400  1.1  mrg     return NULL_RTX;
   3401  1.1  mrg 
   3402  1.1  mrg   if (currently_expanding_gimple_stmt)
   3403  1.1  mrg     stringop_block_profile (currently_expanding_gimple_stmt,
   3404  1.1  mrg 			    &expected_align, &expected_size);
   3405  1.1  mrg 
   3406  1.1  mrg   if (expected_align < dest_align)
   3407  1.1  mrg     expected_align = dest_align;
   3408  1.1  mrg   dest_mem = get_memory_rtx (dest, len);
   3409  1.1  mrg   set_mem_align (dest_mem, dest_align);
   3410  1.1  mrg   len_rtx = expand_normal (len);
   3411  1.1  mrg   determine_block_size (len, len_rtx, &min_size, &max_size,
   3412  1.1  mrg 			&probable_max_size);
   3413  1.1  mrg 
   3414  1.1  mrg   /* Try to get the byte representation of the constant SRC points to,
   3415  1.1  mrg      with its byte size in NBYTES.  */
   3416  1.1  mrg   unsigned HOST_WIDE_INT nbytes;
   3417  1.1  mrg   const char *rep = getbyterep (src, &nbytes);
   3418  1.1  mrg 
   3419  1.1  mrg   /* If the function's constant bound LEN_RTX is less than or equal
   3420  1.1  mrg      to the byte size of the representation of the constant argument,
   3421  1.1  mrg      and if block move would be done by pieces, we can avoid loading
   3422  1.1  mrg      the bytes from memory and only store the computed constant.
   3423  1.1  mrg      This works in the overlap (memmove) case as well because
   3424  1.1  mrg      store_by_pieces just generates a series of stores of constants
   3425  1.1  mrg      from the representation returned by getbyterep().  */
   3426  1.1  mrg   if (rep
   3427  1.1  mrg       && CONST_INT_P (len_rtx)
   3428  1.1  mrg       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
   3429  1.1  mrg       && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
   3430  1.1  mrg 			      CONST_CAST (char *, rep),
   3431  1.1  mrg 			      dest_align, false))
   3432  1.1  mrg     {
   3433  1.1  mrg       dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
   3434  1.1  mrg 				  builtin_memcpy_read_str,
   3435  1.1  mrg 				  CONST_CAST (char *, rep),
   3436  1.1  mrg 				  dest_align, false, retmode);
   3437  1.1  mrg       dest_mem = force_operand (XEXP (dest_mem, 0), target);
   3438  1.1  mrg       dest_mem = convert_memory_address (ptr_mode, dest_mem);
   3439  1.1  mrg       return dest_mem;
   3440  1.1  mrg     }
   3441  1.1  mrg 
   3442  1.1  mrg   src_mem = get_memory_rtx (src, len);
   3443  1.1  mrg   set_mem_align (src_mem, src_align);
   3444  1.1  mrg 
   3445  1.1  mrg   /* Copy word part most expediently.  */
   3446  1.1  mrg   enum block_op_methods method = BLOCK_OP_NORMAL;
   3447  1.1  mrg   if (CALL_EXPR_TAILCALL (exp)
   3448  1.1  mrg       && (retmode == RETURN_BEGIN || target == const0_rtx))
   3449  1.1  mrg     method = BLOCK_OP_TAILCALL;
   3450  1.1  mrg   bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
   3451  1.1  mrg 			   && retmode == RETURN_END
   3452  1.1  mrg 			   && !might_overlap
   3453  1.1  mrg 			   && target != const0_rtx);
   3454  1.1  mrg   if (use_mempcpy_call)
   3455  1.1  mrg     method = BLOCK_OP_NO_LIBCALL_RET;
   3456  1.1  mrg   dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
   3457  1.1  mrg 				     expected_align, expected_size,
   3458  1.1  mrg 				     min_size, max_size, probable_max_size,
   3459  1.1  mrg 				     use_mempcpy_call, &is_move_done,
   3460  1.1  mrg 				     might_overlap);
   3461  1.1  mrg 
   3462  1.1  mrg   /* Bail out when a mempcpy call would be expanded as libcall and when
   3463  1.1  mrg      we have a target that provides a fast implementation
   3464  1.1  mrg      of mempcpy routine.  */
   3465  1.1  mrg   if (!is_move_done)
   3466  1.1  mrg     return NULL_RTX;
   3467  1.1  mrg 
   3468  1.1  mrg   if (dest_addr == pc_rtx)
   3469  1.1  mrg     return NULL_RTX;
   3470  1.1  mrg 
   3471  1.1  mrg   if (dest_addr == 0)
   3472  1.1  mrg     {
   3473  1.1  mrg       dest_addr = force_operand (XEXP (dest_mem, 0), target);
   3474  1.1  mrg       dest_addr = convert_memory_address (ptr_mode, dest_addr);
   3475  1.1  mrg     }
   3476  1.1  mrg 
   3477  1.1  mrg   if (retmode != RETURN_BEGIN && target != const0_rtx)
   3478  1.1  mrg     {
   3479  1.1  mrg       dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
   3480  1.1  mrg       /* stpcpy pointer to last byte.  */
   3481  1.1  mrg       if (retmode == RETURN_END_MINUS_ONE)
   3482  1.1  mrg 	dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
   3483  1.1  mrg     }
   3484  1.1  mrg 
   3485  1.1  mrg   return dest_addr;
   3486  1.1  mrg }
   3487  1.1  mrg 
   3488  1.1  mrg static rtx
   3489  1.1  mrg expand_builtin_mempcpy_args (tree dest, tree src, tree len,
   3490  1.1  mrg 			     rtx target, tree orig_exp, memop_ret retmode)
   3491  1.1  mrg {
   3492  1.1  mrg   return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
   3493  1.1  mrg 					  retmode, false);
   3494  1.1  mrg }
   3495  1.1  mrg 
   3496  1.1  mrg /* Expand into a movstr instruction, if one is available.  Return NULL_RTX if
   3497  1.1  mrg    we failed, the caller should emit a normal call, otherwise try to
   3498  1.1  mrg    get the result in TARGET, if convenient.
   3499  1.1  mrg    Return value is based on RETMODE argument.  */
   3500  1.1  mrg 
   3501  1.1  mrg static rtx
   3502  1.1  mrg expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
   3503  1.1  mrg {
   3504  1.1  mrg   class expand_operand ops[3];
   3505  1.1  mrg   rtx dest_mem;
   3506  1.1  mrg   rtx src_mem;
   3507  1.1  mrg 
   3508  1.1  mrg   if (!targetm.have_movstr ())
   3509  1.1  mrg     return NULL_RTX;
   3510  1.1  mrg 
   3511  1.1  mrg   dest_mem = get_memory_rtx (dest, NULL);
   3512  1.1  mrg   src_mem = get_memory_rtx (src, NULL);
   3513  1.1  mrg   if (retmode == RETURN_BEGIN)
   3514  1.1  mrg     {
   3515  1.1  mrg       target = force_reg (Pmode, XEXP (dest_mem, 0));
   3516  1.1  mrg       dest_mem = replace_equiv_address (dest_mem, target);
   3517  1.1  mrg     }
   3518  1.1  mrg 
   3519  1.1  mrg   create_output_operand (&ops[0],
   3520  1.1  mrg 			 retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
   3521  1.1  mrg   create_fixed_operand (&ops[1], dest_mem);
   3522  1.1  mrg   create_fixed_operand (&ops[2], src_mem);
   3523  1.1  mrg   if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
   3524  1.1  mrg     return NULL_RTX;
   3525  1.1  mrg 
   3526  1.1  mrg   if (retmode != RETURN_BEGIN && target != const0_rtx)
   3527  1.1  mrg     {
   3528  1.1  mrg       target = ops[0].value;
   3529  1.1  mrg       /* movstr is supposed to set end to the address of the NUL
   3530  1.1  mrg 	 terminator.  If the caller requested a mempcpy-like return value,
   3531  1.1  mrg 	 adjust it.  */
   3532  1.1  mrg       if (retmode == RETURN_END)
   3533  1.1  mrg 	{
   3534  1.1  mrg 	  rtx tem = plus_constant (GET_MODE (target),
   3535  1.1  mrg 				   gen_lowpart (GET_MODE (target), target), 1);
   3536  1.1  mrg 	  emit_move_insn (target, force_operand (tem, NULL_RTX));
   3537  1.1  mrg 	}
   3538  1.1  mrg     }
   3539  1.1  mrg   return target;
   3540  1.1  mrg }
   3541  1.1  mrg 
   3542  1.1  mrg /* Expand expression EXP, which is a call to the strcpy builtin.  Return
   3543  1.1  mrg    NULL_RTX if we failed the caller should emit a normal call, otherwise
   3544  1.1  mrg    try to get the result in TARGET, if convenient (and in mode MODE if that's
   3545  1.1  mrg    convenient).  */
   3546  1.1  mrg 
   3547  1.1  mrg static rtx
   3548  1.1  mrg expand_builtin_strcpy (tree exp, rtx target)
   3549  1.1  mrg {
   3550  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   3551  1.1  mrg     return NULL_RTX;
   3552  1.1  mrg 
   3553  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3554  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   3555  1.1  mrg 
   3556  1.1  mrg   return expand_builtin_strcpy_args (exp, dest, src, target);
   3557  1.1  mrg }
   3558  1.1  mrg 
   3559  1.1  mrg /* Helper function to do the actual work for expand_builtin_strcpy.  The
   3560  1.1  mrg    arguments to the builtin_strcpy call DEST and SRC are broken out
   3561  1.1  mrg    so that this can also be called without constructing an actual CALL_EXPR.
   3562  1.1  mrg    The other arguments and return value are the same as for
   3563  1.1  mrg    expand_builtin_strcpy.  */
   3564  1.1  mrg 
   3565  1.1  mrg static rtx
   3566  1.1  mrg expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target)
   3567  1.1  mrg {
   3568  1.1  mrg   return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
   3569  1.1  mrg }
   3570  1.1  mrg 
   3571  1.1  mrg /* Expand a call EXP to the stpcpy builtin.
   3572  1.1  mrg    Return NULL_RTX if we failed the caller should emit a normal call,
   3573  1.1  mrg    otherwise try to get the result in TARGET, if convenient (and in
   3574  1.1  mrg    mode MODE if that's convenient).  */
   3575  1.1  mrg 
   3576  1.1  mrg static rtx
   3577  1.1  mrg expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
   3578  1.1  mrg {
   3579  1.1  mrg   tree dst, src;
   3580  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   3581  1.1  mrg 
   3582  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   3583  1.1  mrg     return NULL_RTX;
   3584  1.1  mrg 
   3585  1.1  mrg   dst = CALL_EXPR_ARG (exp, 0);
   3586  1.1  mrg   src = CALL_EXPR_ARG (exp, 1);
   3587  1.1  mrg 
   3588  1.1  mrg   /* If return value is ignored, transform stpcpy into strcpy.  */
   3589  1.1  mrg   if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
   3590  1.1  mrg     {
   3591  1.1  mrg       tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
   3592  1.1  mrg       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
   3593  1.1  mrg       return expand_expr (result, target, mode, EXPAND_NORMAL);
   3594  1.1  mrg     }
   3595  1.1  mrg   else
   3596  1.1  mrg     {
   3597  1.1  mrg       tree len, lenp1;
   3598  1.1  mrg       rtx ret;
   3599  1.1  mrg 
   3600  1.1  mrg       /* Ensure we get an actual string whose length can be evaluated at
   3601  1.1  mrg 	 compile-time, not an expression containing a string.  This is
   3602  1.1  mrg 	 because the latter will potentially produce pessimized code
   3603  1.1  mrg 	 when used to produce the return value.  */
   3604  1.1  mrg       c_strlen_data lendata = { };
   3605  1.1  mrg       if (!c_getstr (src)
   3606  1.1  mrg 	  || !(len = c_strlen (src, 0, &lendata, 1)))
   3607  1.1  mrg 	return expand_movstr (dst, src, target,
   3608  1.1  mrg 			      /*retmode=*/ RETURN_END_MINUS_ONE);
   3609  1.1  mrg 
   3610  1.1  mrg       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
   3611  1.1  mrg       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
   3612  1.1  mrg 					 target, exp,
   3613  1.1  mrg 					 /*retmode=*/ RETURN_END_MINUS_ONE);
   3614  1.1  mrg 
   3615  1.1  mrg       if (ret)
   3616  1.1  mrg 	return ret;
   3617  1.1  mrg 
   3618  1.1  mrg       if (TREE_CODE (len) == INTEGER_CST)
   3619  1.1  mrg 	{
   3620  1.1  mrg 	  rtx len_rtx = expand_normal (len);
   3621  1.1  mrg 
   3622  1.1  mrg 	  if (CONST_INT_P (len_rtx))
   3623  1.1  mrg 	    {
   3624  1.1  mrg 	      ret = expand_builtin_strcpy_args (exp, dst, src, target);
   3625  1.1  mrg 
   3626  1.1  mrg 	      if (ret)
   3627  1.1  mrg 		{
   3628  1.1  mrg 		  if (! target)
   3629  1.1  mrg 		    {
   3630  1.1  mrg 		      if (mode != VOIDmode)
   3631  1.1  mrg 			target = gen_reg_rtx (mode);
   3632  1.1  mrg 		      else
   3633  1.1  mrg 			target = gen_reg_rtx (GET_MODE (ret));
   3634  1.1  mrg 		    }
   3635  1.1  mrg 		  if (GET_MODE (target) != GET_MODE (ret))
   3636  1.1  mrg 		    ret = gen_lowpart (GET_MODE (target), ret);
   3637  1.1  mrg 
   3638  1.1  mrg 		  ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
   3639  1.1  mrg 		  ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
   3640  1.1  mrg 		  gcc_assert (ret);
   3641  1.1  mrg 
   3642  1.1  mrg 		  return target;
   3643  1.1  mrg 		}
   3644  1.1  mrg 	    }
   3645  1.1  mrg 	}
   3646  1.1  mrg 
   3647  1.1  mrg       return expand_movstr (dst, src, target,
   3648  1.1  mrg 			    /*retmode=*/ RETURN_END_MINUS_ONE);
   3649  1.1  mrg     }
   3650  1.1  mrg }
   3651  1.1  mrg 
   3652  1.1  mrg /* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
   3653  1.1  mrg    arguments while being careful to avoid duplicate warnings (which could
   3654  1.1  mrg    be issued if the expander were to expand the call, resulting in it
   3655  1.1  mrg    being emitted in expand_call().  */
   3656  1.1  mrg 
   3657  1.1  mrg static rtx
   3658  1.1  mrg expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
   3659  1.1  mrg {
   3660  1.1  mrg   if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
   3661  1.1  mrg     {
   3662  1.1  mrg       /* The call has been successfully expanded.  Check for nonstring
   3663  1.1  mrg 	 arguments and issue warnings as appropriate.  */
   3664  1.1  mrg       maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
   3665  1.1  mrg       return ret;
   3666  1.1  mrg     }
   3667  1.1  mrg 
   3668  1.1  mrg   return NULL_RTX;
   3669  1.1  mrg }
   3670  1.1  mrg 
   3671  1.1  mrg /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
   3672  1.1  mrg    bytes from constant string DATA + OFFSET and return it as target
   3673  1.1  mrg    constant.  */
   3674  1.1  mrg 
   3675  1.1  mrg rtx
   3676  1.1  mrg builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
   3677  1.1  mrg 			  fixed_size_mode mode)
   3678  1.1  mrg {
   3679  1.1  mrg   const char *str = (const char *) data;
   3680  1.1  mrg 
   3681  1.1  mrg   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
   3682  1.1  mrg     return const0_rtx;
   3683  1.1  mrg 
   3684  1.1  mrg   /* The by-pieces infrastructure does not try to pick a vector mode
   3685  1.1  mrg      for strncpy expansion.  */
   3686  1.1  mrg   return c_readstr (str + offset, as_a <scalar_int_mode> (mode));
   3687  1.1  mrg }
   3688  1.1  mrg 
   3689  1.1  mrg /* Helper to check the sizes of sequences and the destination of calls
   3690  1.1  mrg    to __builtin_strncat and __builtin___strncat_chk.  Returns true on
   3691  1.1  mrg    success (no overflow or invalid sizes), false otherwise.  */
   3692  1.1  mrg 
   3693  1.1  mrg static bool
   3694  1.1  mrg check_strncat_sizes (tree exp, tree objsize)
   3695  1.1  mrg {
   3696  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3697  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   3698  1.1  mrg   tree maxread = CALL_EXPR_ARG (exp, 2);
   3699  1.1  mrg 
   3700  1.1  mrg   /* Try to determine the range of lengths that the source expression
   3701  1.1  mrg      refers to.  */
   3702  1.1  mrg   c_strlen_data lendata = { };
   3703  1.1  mrg   get_range_strlen (src, &lendata, /* eltsize = */ 1);
   3704  1.1  mrg 
   3705  1.1  mrg   /* Try to verify that the destination is big enough for the shortest
   3706  1.1  mrg      string.  */
   3707  1.1  mrg 
   3708  1.1  mrg   access_data data (nullptr, exp, access_read_write, maxread, true);
   3709  1.1  mrg   if (!objsize && warn_stringop_overflow)
   3710  1.1  mrg     {
   3711  1.1  mrg       /* If it hasn't been provided by __strncat_chk, try to determine
   3712  1.1  mrg 	 the size of the destination object into which the source is
   3713  1.1  mrg 	 being copied.  */
   3714  1.1  mrg       objsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst);
   3715  1.1  mrg     }
   3716  1.1  mrg 
   3717  1.1  mrg   /* Add one for the terminating nul.  */
   3718  1.1  mrg   tree srclen = (lendata.minlen
   3719  1.1  mrg 		 ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
   3720  1.1  mrg 				size_one_node)
   3721  1.1  mrg 		 : NULL_TREE);
   3722  1.1  mrg 
   3723  1.1  mrg   /* The strncat function copies at most MAXREAD bytes and always appends
   3724  1.1  mrg      the terminating nul so the specified upper bound should never be equal
   3725  1.1  mrg      to (or greater than) the size of the destination.  */
   3726  1.1  mrg   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
   3727  1.1  mrg       && tree_int_cst_equal (objsize, maxread))
   3728  1.1  mrg     {
   3729  1.1  mrg       location_t loc = EXPR_LOCATION (exp);
   3730  1.1  mrg       warning_at (loc, OPT_Wstringop_overflow_,
   3731  1.1  mrg 		  "%qD specified bound %E equals destination size",
   3732  1.1  mrg 		  get_callee_fndecl (exp), maxread);
   3733  1.1  mrg 
   3734  1.1  mrg       return false;
   3735  1.1  mrg     }
   3736  1.1  mrg 
   3737  1.1  mrg   if (!srclen
   3738  1.1  mrg       || (maxread && tree_fits_uhwi_p (maxread)
   3739  1.1  mrg 	  && tree_fits_uhwi_p (srclen)
   3740  1.1  mrg 	  && tree_int_cst_lt (maxread, srclen)))
   3741  1.1  mrg     srclen = maxread;
   3742  1.1  mrg 
   3743  1.1  mrg   /* The number of bytes to write is LEN but check_access will alsoa
   3744  1.1  mrg      check SRCLEN if LEN's value isn't known.  */
   3745  1.1  mrg   return check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen,
   3746  1.1  mrg 		       objsize, data.mode, &data);
   3747  1.1  mrg }
   3748  1.1  mrg 
   3749  1.1  mrg /* Expand expression EXP, which is a call to the strncpy builtin.  Return
   3750  1.1  mrg    NULL_RTX if we failed the caller should emit a normal call.  */
   3751  1.1  mrg 
   3752  1.1  mrg static rtx
   3753  1.1  mrg expand_builtin_strncpy (tree exp, rtx target)
   3754  1.1  mrg {
   3755  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   3756  1.1  mrg 
   3757  1.1  mrg   if (!validate_arglist (exp,
   3758  1.1  mrg 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   3759  1.1  mrg     return NULL_RTX;
   3760  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3761  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   3762  1.1  mrg   /* The number of bytes to write (not the maximum).  */
   3763  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   3764  1.1  mrg 
   3765  1.1  mrg   /* The length of the source sequence.  */
   3766  1.1  mrg   tree slen = c_strlen (src, 1);
   3767  1.1  mrg 
   3768  1.1  mrg   /* We must be passed a constant len and src parameter.  */
   3769  1.1  mrg   if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
   3770  1.1  mrg     return NULL_RTX;
   3771  1.1  mrg 
   3772  1.1  mrg   slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
   3773  1.1  mrg 
   3774  1.1  mrg   /* We're required to pad with trailing zeros if the requested
   3775  1.1  mrg      len is greater than strlen(s2)+1.  In that case try to
   3776  1.1  mrg      use store_by_pieces, if it fails, punt.  */
   3777  1.1  mrg   if (tree_int_cst_lt (slen, len))
   3778  1.1  mrg     {
   3779  1.1  mrg       unsigned int dest_align = get_pointer_alignment (dest);
   3780  1.1  mrg       const char *p = c_getstr (src);
   3781  1.1  mrg       rtx dest_mem;
   3782  1.1  mrg 
   3783  1.1  mrg       if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
   3784  1.1  mrg 	  || !can_store_by_pieces (tree_to_uhwi (len),
   3785  1.1  mrg 				   builtin_strncpy_read_str,
   3786  1.1  mrg 				   CONST_CAST (char *, p),
   3787  1.1  mrg 				   dest_align, false))
   3788  1.1  mrg 	return NULL_RTX;
   3789  1.1  mrg 
   3790  1.1  mrg       dest_mem = get_memory_rtx (dest, len);
   3791  1.1  mrg       store_by_pieces (dest_mem, tree_to_uhwi (len),
   3792  1.1  mrg 		       builtin_strncpy_read_str,
   3793  1.1  mrg 		       CONST_CAST (char *, p), dest_align, false,
   3794  1.1  mrg 		       RETURN_BEGIN);
   3795  1.1  mrg       dest_mem = force_operand (XEXP (dest_mem, 0), target);
   3796  1.1  mrg       dest_mem = convert_memory_address (ptr_mode, dest_mem);
   3797  1.1  mrg       return dest_mem;
   3798  1.1  mrg     }
   3799  1.1  mrg 
   3800  1.1  mrg   return NULL_RTX;
   3801  1.1  mrg }
   3802  1.1  mrg 
   3803  1.1  mrg /* Return the RTL of a register in MODE generated from PREV in the
   3804  1.1  mrg    previous iteration.  */
   3805  1.1  mrg 
   3806  1.1  mrg static rtx
   3807  1.1  mrg gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
   3808  1.1  mrg {
   3809  1.1  mrg   rtx target = nullptr;
   3810  1.1  mrg   if (prev != nullptr && prev->data != nullptr)
   3811  1.1  mrg     {
   3812  1.1  mrg       /* Use the previous data in the same mode.  */
   3813  1.1  mrg       if (prev->mode == mode)
   3814  1.1  mrg 	return prev->data;
   3815  1.1  mrg 
   3816  1.1  mrg       fixed_size_mode prev_mode = prev->mode;
   3817  1.1  mrg 
   3818  1.1  mrg       /* Don't use the previous data to write QImode if it is in a
   3819  1.1  mrg 	 vector mode.  */
   3820  1.1  mrg       if (VECTOR_MODE_P (prev_mode) && mode == QImode)
   3821  1.1  mrg 	return target;
   3822  1.1  mrg 
   3823  1.1  mrg       rtx prev_rtx = prev->data;
   3824  1.1  mrg 
   3825  1.1  mrg       if (REG_P (prev_rtx)
   3826  1.1  mrg 	  && HARD_REGISTER_P (prev_rtx)
   3827  1.1  mrg 	  && lowpart_subreg_regno (REGNO (prev_rtx), prev_mode, mode) < 0)
   3828  1.1  mrg 	{
   3829  1.1  mrg 	  /* This case occurs when PREV_MODE is a vector and when
   3830  1.1  mrg 	     MODE is too small to store using vector operations.
   3831  1.1  mrg 	     After register allocation, the code will need to move the
   3832  1.1  mrg 	     lowpart of the vector register into a non-vector register.
   3833  1.1  mrg 
   3834  1.1  mrg 	     Also, the target has chosen to use a hard register
   3835  1.1  mrg 	     instead of going with the default choice of using a
   3836  1.1  mrg 	     pseudo register.  We should respect that choice and try to
   3837  1.1  mrg 	     avoid creating a pseudo register with the same mode as the
   3838  1.1  mrg 	     current hard register.
   3839  1.1  mrg 
   3840  1.1  mrg 	     In principle, we could just use a lowpart MODE subreg of
   3841  1.1  mrg 	     the vector register.  However, the vector register mode might
   3842  1.1  mrg 	     be too wide for non-vector registers, and we already know
   3843  1.1  mrg 	     that the non-vector mode is too small for vector registers.
   3844  1.1  mrg 	     It's therefore likely that we'd need to spill to memory in
   3845  1.1  mrg 	     the vector mode and reload the non-vector value from there.
   3846  1.1  mrg 
   3847  1.1  mrg 	     Try to avoid that by reducing the vector register to the
   3848  1.1  mrg 	     smallest size that it can hold.  This should increase the
   3849  1.1  mrg 	     chances that non-vector registers can hold both the inner
   3850  1.1  mrg 	     and outer modes of the subreg that we generate later.  */
   3851  1.1  mrg 	  machine_mode m;
   3852  1.1  mrg 	  fixed_size_mode candidate;
   3853  1.1  mrg 	  FOR_EACH_MODE_IN_CLASS (m, GET_MODE_CLASS (mode))
   3854  1.1  mrg 	    if (is_a<fixed_size_mode> (m, &candidate))
   3855  1.1  mrg 	      {
   3856  1.1  mrg 		if (GET_MODE_SIZE (candidate)
   3857  1.1  mrg 		    >= GET_MODE_SIZE (prev_mode))
   3858  1.1  mrg 		  break;
   3859  1.1  mrg 		if (GET_MODE_SIZE (candidate) >= GET_MODE_SIZE (mode)
   3860  1.1  mrg 		    && lowpart_subreg_regno (REGNO (prev_rtx),
   3861  1.1  mrg 					     prev_mode, candidate) >= 0)
   3862  1.1  mrg 		  {
   3863  1.1  mrg 		    target = lowpart_subreg (candidate, prev_rtx,
   3864  1.1  mrg 					     prev_mode);
   3865  1.1  mrg 		    prev_rtx = target;
   3866  1.1  mrg 		    prev_mode = candidate;
   3867  1.1  mrg 		    break;
   3868  1.1  mrg 		  }
   3869  1.1  mrg 	      }
   3870  1.1  mrg 	  if (target == nullptr)
   3871  1.1  mrg 	    prev_rtx = copy_to_reg (prev_rtx);
   3872  1.1  mrg 	}
   3873  1.1  mrg 
   3874  1.1  mrg       target = lowpart_subreg (mode, prev_rtx, prev_mode);
   3875  1.1  mrg     }
   3876  1.1  mrg   return target;
   3877  1.1  mrg }
   3878  1.1  mrg 
   3879  1.1  mrg /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
   3880  1.1  mrg    bytes from constant string DATA + OFFSET and return it as target
   3881  1.1  mrg    constant.  If PREV isn't nullptr, it has the RTL info from the
   3882  1.1  mrg    previous iteration.  */
   3883  1.1  mrg 
   3884  1.1  mrg rtx
   3885  1.1  mrg builtin_memset_read_str (void *data, void *prev,
   3886  1.1  mrg 			 HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
   3887  1.1  mrg 			 fixed_size_mode mode)
   3888  1.1  mrg {
   3889  1.1  mrg   const char *c = (const char *) data;
   3890  1.1  mrg   unsigned int size = GET_MODE_SIZE (mode);
   3891  1.1  mrg 
   3892  1.1  mrg   rtx target = gen_memset_value_from_prev ((by_pieces_prev *) prev,
   3893  1.1  mrg 					   mode);
   3894  1.1  mrg   if (target != nullptr)
   3895  1.1  mrg     return target;
   3896  1.1  mrg   rtx src = gen_int_mode (*c, QImode);
   3897  1.1  mrg 
   3898  1.1  mrg   if (VECTOR_MODE_P (mode))
   3899  1.1  mrg     {
   3900  1.1  mrg       gcc_assert (GET_MODE_INNER (mode) == QImode);
   3901  1.1  mrg 
   3902  1.1  mrg       rtx const_vec = gen_const_vec_duplicate (mode, src);
   3903  1.1  mrg       if (prev == NULL)
   3904  1.1  mrg 	/* Return CONST_VECTOR when called by a query function.  */
   3905  1.1  mrg 	return const_vec;
   3906  1.1  mrg 
   3907  1.1  mrg       /* Use the move expander with CONST_VECTOR.  */
   3908  1.1  mrg       target = targetm.gen_memset_scratch_rtx (mode);
   3909  1.1  mrg       emit_move_insn (target, const_vec);
   3910  1.1  mrg       return target;
   3911  1.1  mrg     }
   3912  1.1  mrg 
   3913  1.1  mrg   char *p = XALLOCAVEC (char, size);
   3914  1.1  mrg 
   3915  1.1  mrg   memset (p, *c, size);
   3916  1.1  mrg 
   3917  1.1  mrg   /* Vector modes should be handled above.  */
   3918  1.1  mrg   return c_readstr (p, as_a <scalar_int_mode> (mode));
   3919  1.1  mrg }
   3920  1.1  mrg 
   3921  1.1  mrg /* Callback routine for store_by_pieces.  Return the RTL of a register
   3922  1.1  mrg    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
   3923  1.1  mrg    char value given in the RTL register data.  For example, if mode is
   3924  1.1  mrg    4 bytes wide, return the RTL for 0x01010101*data.  If PREV isn't
   3925  1.1  mrg    nullptr, it has the RTL info from the previous iteration.  */
   3926  1.1  mrg 
   3927  1.1  mrg static rtx
   3928  1.1  mrg builtin_memset_gen_str (void *data, void *prev,
   3929  1.1  mrg 			HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
   3930  1.1  mrg 			fixed_size_mode mode)
   3931  1.1  mrg {
   3932  1.1  mrg   rtx target, coeff;
   3933  1.1  mrg   size_t size;
   3934  1.1  mrg   char *p;
   3935  1.1  mrg 
   3936  1.1  mrg   size = GET_MODE_SIZE (mode);
   3937  1.1  mrg   if (size == 1)
   3938  1.1  mrg     return (rtx) data;
   3939  1.1  mrg 
   3940  1.1  mrg   target = gen_memset_value_from_prev ((by_pieces_prev *) prev, mode);
   3941  1.1  mrg   if (target != nullptr)
   3942  1.1  mrg     return target;
   3943  1.1  mrg 
   3944  1.1  mrg   if (VECTOR_MODE_P (mode))
   3945  1.1  mrg     {
   3946  1.1  mrg       gcc_assert (GET_MODE_INNER (mode) == QImode);
   3947  1.1  mrg 
   3948  1.1  mrg       /* vec_duplicate_optab is a precondition to pick a vector mode for
   3949  1.1  mrg 	 the memset expander.  */
   3950  1.1  mrg       insn_code icode = optab_handler (vec_duplicate_optab, mode);
   3951  1.1  mrg 
   3952  1.1  mrg       target = targetm.gen_memset_scratch_rtx (mode);
   3953  1.1  mrg       class expand_operand ops[2];
   3954  1.1  mrg       create_output_operand (&ops[0], target, mode);
   3955  1.1  mrg       create_input_operand (&ops[1], (rtx) data, QImode);
   3956  1.1  mrg       expand_insn (icode, 2, ops);
   3957  1.1  mrg       if (!rtx_equal_p (target, ops[0].value))
   3958  1.1  mrg 	emit_move_insn (target, ops[0].value);
   3959  1.1  mrg 
   3960  1.1  mrg       return target;
   3961  1.1  mrg     }
   3962  1.1  mrg 
   3963  1.1  mrg   p = XALLOCAVEC (char, size);
   3964  1.1  mrg   memset (p, 1, size);
   3965  1.1  mrg   /* Vector modes should be handled above.  */
   3966  1.1  mrg   coeff = c_readstr (p, as_a <scalar_int_mode> (mode));
   3967  1.1  mrg 
   3968  1.1  mrg   target = convert_to_mode (mode, (rtx) data, 1);
   3969  1.1  mrg   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
   3970  1.1  mrg   return force_reg (mode, target);
   3971  1.1  mrg }
   3972  1.1  mrg 
   3973  1.1  mrg /* Expand expression EXP, which is a call to the memset builtin.  Return
   3974  1.1  mrg    NULL_RTX if we failed the caller should emit a normal call, otherwise
   3975  1.1  mrg    try to get the result in TARGET, if convenient (and in mode MODE if that's
   3976  1.1  mrg    convenient).  */
   3977  1.1  mrg 
   3978  1.1  mrg rtx
   3979  1.1  mrg expand_builtin_memset (tree exp, rtx target, machine_mode mode)
   3980  1.1  mrg {
   3981  1.1  mrg   if (!validate_arglist (exp,
   3982  1.1  mrg  			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
   3983  1.1  mrg     return NULL_RTX;
   3984  1.1  mrg 
   3985  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   3986  1.1  mrg   tree val = CALL_EXPR_ARG (exp, 1);
   3987  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   3988  1.1  mrg 
   3989  1.1  mrg   return expand_builtin_memset_args (dest, val, len, target, mode, exp);
   3990  1.1  mrg }
   3991  1.1  mrg 
   3992  1.1  mrg /* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO.
   3993  1.1  mrg    Return TRUE if successful, FALSE otherwise.  TO is assumed to be
   3994  1.1  mrg    aligned at an ALIGN-bits boundary.  LEN must be a multiple of
   3995  1.1  mrg    1<<CTZ_LEN between MIN_LEN and MAX_LEN.
   3996  1.1  mrg 
   3997  1.1  mrg    The strategy is to issue one store_by_pieces for each power of two,
   3998  1.1  mrg    from most to least significant, guarded by a test on whether there
   3999  1.1  mrg    are at least that many bytes left to copy in LEN.
   4000  1.1  mrg 
   4001  1.1  mrg    ??? Should we skip some powers of two in favor of loops?  Maybe start
   4002  1.1  mrg    at the max of TO/LEN/word alignment, at least when optimizing for
   4003  1.1  mrg    size, instead of ensuring O(log len) dynamic compares?  */
   4004  1.1  mrg 
   4005  1.1  mrg bool
   4006  1.1  mrg try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len,
   4007  1.1  mrg 			      unsigned HOST_WIDE_INT min_len,
   4008  1.1  mrg 			      unsigned HOST_WIDE_INT max_len,
   4009  1.1  mrg 			      rtx val, char valc, unsigned int align)
   4010  1.1  mrg {
   4011  1.1  mrg   int max_bits = floor_log2 (max_len);
   4012  1.1  mrg   int min_bits = floor_log2 (min_len);
   4013  1.1  mrg   int sctz_len = ctz_len;
   4014  1.1  mrg 
   4015  1.1  mrg   gcc_checking_assert (sctz_len >= 0);
   4016  1.1  mrg 
   4017  1.1  mrg   if (val)
   4018  1.1  mrg     valc = 1;
   4019  1.1  mrg 
   4020  1.1  mrg   /* Bits more significant than TST_BITS are part of the shared prefix
   4021  1.1  mrg      in the binary representation of both min_len and max_len.  Since
   4022  1.1  mrg      they're identical, we don't need to test them in the loop.  */
   4023  1.1  mrg   int tst_bits = (max_bits != min_bits ? max_bits
   4024  1.1  mrg 		  : floor_log2 (max_len ^ min_len));
   4025  1.1  mrg 
   4026  1.1  mrg   /* Check whether it's profitable to start by storing a fixed BLKSIZE
   4027  1.1  mrg      bytes, to lower max_bits.  In the unlikely case of a constant LEN
   4028  1.1  mrg      (implied by identical MAX_LEN and MIN_LEN), we want to issue a
   4029  1.1  mrg      single store_by_pieces, but otherwise, select the minimum multiple
   4030  1.1  mrg      of the ALIGN (in bytes) and of the MCD of the possible LENs, that
   4031  1.1  mrg      brings MAX_LEN below TST_BITS, if that's lower than min_len.  */
   4032  1.1  mrg   unsigned HOST_WIDE_INT blksize;
   4033  1.1  mrg   if (max_len > min_len)
   4034  1.1  mrg     {
   4035  1.1  mrg       unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
   4036  1.1  mrg 					  align / BITS_PER_UNIT);
   4037  1.1  mrg       blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
   4038  1.1  mrg       blksize &= ~(alrng - 1);
   4039  1.1  mrg     }
   4040  1.1  mrg   else if (max_len == min_len)
   4041  1.1  mrg     blksize = max_len;
   4042  1.1  mrg   else
   4043  1.1  mrg     /* Huh, max_len < min_len?  Punt.  See pr100843.c.  */
   4044  1.1  mrg     return false;
   4045  1.1  mrg   if (min_len >= blksize)
   4046  1.1  mrg     {
   4047  1.1  mrg       min_len -= blksize;
   4048  1.1  mrg       min_bits = floor_log2 (min_len);
   4049  1.1  mrg       max_len -= blksize;
   4050  1.1  mrg       max_bits = floor_log2 (max_len);
   4051  1.1  mrg 
   4052  1.1  mrg       tst_bits = (max_bits != min_bits ? max_bits
   4053  1.1  mrg 		 : floor_log2 (max_len ^ min_len));
   4054  1.1  mrg     }
   4055  1.1  mrg   else
   4056  1.1  mrg     blksize = 0;
   4057  1.1  mrg 
   4058  1.1  mrg   /* Check that we can use store by pieces for the maximum store count
   4059  1.1  mrg      we may issue (initial fixed-size block, plus conditional
   4060  1.1  mrg      power-of-two-sized from max_bits to ctz_len.  */
   4061  1.1  mrg   unsigned HOST_WIDE_INT xlenest = blksize;
   4062  1.1  mrg   if (max_bits >= 0)
   4063  1.1  mrg     xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
   4064  1.1  mrg 		- (HOST_WIDE_INT_1U << ctz_len));
   4065  1.1  mrg   if (!can_store_by_pieces (xlenest, builtin_memset_read_str,
   4066  1.1  mrg 			    &valc, align, true))
   4067  1.1  mrg     return false;
   4068  1.1  mrg 
   4069  1.1  mrg   by_pieces_constfn constfun;
   4070  1.1  mrg   void *constfundata;
   4071  1.1  mrg   if (val)
   4072  1.1  mrg     {
   4073  1.1  mrg       constfun = builtin_memset_gen_str;
   4074  1.1  mrg       constfundata = val = force_reg (TYPE_MODE (unsigned_char_type_node),
   4075  1.1  mrg 				      val);
   4076  1.1  mrg     }
   4077  1.1  mrg   else
   4078  1.1  mrg     {
   4079  1.1  mrg       constfun = builtin_memset_read_str;
   4080  1.1  mrg       constfundata = &valc;
   4081  1.1  mrg     }
   4082  1.1  mrg 
   4083  1.1  mrg   rtx ptr = copy_addr_to_reg (XEXP (to, 0));
   4084  1.1  mrg   rtx rem = copy_to_mode_reg (ptr_mode, convert_to_mode (ptr_mode, len, 0));
   4085  1.1  mrg   to = replace_equiv_address (to, ptr);
   4086  1.1  mrg   set_mem_align (to, align);
   4087  1.1  mrg 
   4088  1.1  mrg   if (blksize)
   4089  1.1  mrg     {
   4090  1.1  mrg       to = store_by_pieces (to, blksize,
   4091  1.1  mrg 			    constfun, constfundata,
   4092  1.1  mrg 			    align, true,
   4093  1.1  mrg 			    max_len != 0 ? RETURN_END : RETURN_BEGIN);
   4094  1.1  mrg       if (max_len == 0)
   4095  1.1  mrg 	return true;
   4096  1.1  mrg 
   4097  1.1  mrg       /* Adjust PTR, TO and REM.  Since TO's address is likely
   4098  1.1  mrg 	 PTR+offset, we have to replace it.  */
   4099  1.1  mrg       emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
   4100  1.1  mrg       to = replace_equiv_address (to, ptr);
   4101  1.1  mrg       rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
   4102  1.1  mrg       emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
   4103  1.1  mrg     }
   4104  1.1  mrg 
   4105  1.1  mrg   /* Iterate over power-of-two block sizes from the maximum length to
   4106  1.1  mrg      the least significant bit possibly set in the length.  */
   4107  1.1  mrg   for (int i = max_bits; i >= sctz_len; i--)
   4108  1.1  mrg     {
   4109  1.1  mrg       rtx_code_label *label = NULL;
   4110  1.1  mrg       blksize = HOST_WIDE_INT_1U << i;
   4111  1.1  mrg 
   4112  1.1  mrg       /* If we're past the bits shared between min_ and max_len, expand
   4113  1.1  mrg 	 a test on the dynamic length, comparing it with the
   4114  1.1  mrg 	 BLKSIZE.  */
   4115  1.1  mrg       if (i <= tst_bits)
   4116  1.1  mrg 	{
   4117  1.1  mrg 	  label = gen_label_rtx ();
   4118  1.1  mrg 	  emit_cmp_and_jump_insns (rem, GEN_INT (blksize), LT, NULL,
   4119  1.1  mrg 				   ptr_mode, 1, label,
   4120  1.1  mrg 				   profile_probability::even ());
   4121  1.1  mrg 	}
   4122  1.1  mrg       /* If we are at a bit that is in the prefix shared by min_ and
   4123  1.1  mrg 	 max_len, skip this BLKSIZE if the bit is clear.  */
   4124  1.1  mrg       else if ((max_len & blksize) == 0)
   4125  1.1  mrg 	continue;
   4126  1.1  mrg 
   4127  1.1  mrg       /* Issue a store of BLKSIZE bytes.  */
   4128  1.1  mrg       to = store_by_pieces (to, blksize,
   4129  1.1  mrg 			    constfun, constfundata,
   4130  1.1  mrg 			    align, true,
   4131  1.1  mrg 			    i != sctz_len ? RETURN_END : RETURN_BEGIN);
   4132  1.1  mrg 
   4133  1.1  mrg       /* Adjust REM and PTR, unless this is the last iteration.  */
   4134  1.1  mrg       if (i != sctz_len)
   4135  1.1  mrg 	{
   4136  1.1  mrg 	  emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
   4137  1.1  mrg 	  to = replace_equiv_address (to, ptr);
   4138  1.1  mrg 	  rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
   4139  1.1  mrg 	  emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
   4140  1.1  mrg 	}
   4141  1.1  mrg 
   4142  1.1  mrg       if (label)
   4143  1.1  mrg 	{
   4144  1.1  mrg 	  emit_label (label);
   4145  1.1  mrg 
   4146  1.1  mrg 	  /* Given conditional stores, the offset can no longer be
   4147  1.1  mrg 	     known, so clear it.  */
   4148  1.1  mrg 	  clear_mem_offset (to);
   4149  1.1  mrg 	}
   4150  1.1  mrg     }
   4151  1.1  mrg 
   4152  1.1  mrg   return true;
   4153  1.1  mrg }
   4154  1.1  mrg 
   4155  1.1  mrg /* Helper function to do the actual work for expand_builtin_memset.  The
   4156  1.1  mrg    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
   4157  1.1  mrg    so that this can also be called without constructing an actual CALL_EXPR.
   4158  1.1  mrg    The other arguments and return value are the same as for
   4159  1.1  mrg    expand_builtin_memset.  */
   4160  1.1  mrg 
   4161  1.1  mrg static rtx
   4162  1.1  mrg expand_builtin_memset_args (tree dest, tree val, tree len,
   4163  1.1  mrg 			    rtx target, machine_mode mode, tree orig_exp)
   4164  1.1  mrg {
   4165  1.1  mrg   tree fndecl, fn;
   4166  1.1  mrg   enum built_in_function fcode;
   4167  1.1  mrg   machine_mode val_mode;
   4168  1.1  mrg   char c;
   4169  1.1  mrg   unsigned int dest_align;
   4170  1.1  mrg   rtx dest_mem, dest_addr, len_rtx;
   4171  1.1  mrg   HOST_WIDE_INT expected_size = -1;
   4172  1.1  mrg   unsigned int expected_align = 0;
   4173  1.1  mrg   unsigned HOST_WIDE_INT min_size;
   4174  1.1  mrg   unsigned HOST_WIDE_INT max_size;
   4175  1.1  mrg   unsigned HOST_WIDE_INT probable_max_size;
   4176  1.1  mrg 
   4177  1.1  mrg   dest_align = get_pointer_alignment (dest);
   4178  1.1  mrg 
   4179  1.1  mrg   /* If DEST is not a pointer type, don't do this operation in-line.  */
   4180  1.1  mrg   if (dest_align == 0)
   4181  1.1  mrg     return NULL_RTX;
   4182  1.1  mrg 
   4183  1.1  mrg   if (currently_expanding_gimple_stmt)
   4184  1.1  mrg     stringop_block_profile (currently_expanding_gimple_stmt,
   4185  1.1  mrg 			    &expected_align, &expected_size);
   4186  1.1  mrg 
   4187  1.1  mrg   if (expected_align < dest_align)
   4188  1.1  mrg     expected_align = dest_align;
   4189  1.1  mrg 
   4190  1.1  mrg   /* If the LEN parameter is zero, return DEST.  */
   4191  1.1  mrg   if (integer_zerop (len))
   4192  1.1  mrg     {
   4193  1.1  mrg       /* Evaluate and ignore VAL in case it has side-effects.  */
   4194  1.1  mrg       expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
   4195  1.1  mrg       return expand_expr (dest, target, mode, EXPAND_NORMAL);
   4196  1.1  mrg     }
   4197  1.1  mrg 
   4198  1.1  mrg   /* Stabilize the arguments in case we fail.  */
   4199  1.1  mrg   dest = builtin_save_expr (dest);
   4200  1.1  mrg   val = builtin_save_expr (val);
   4201  1.1  mrg   len = builtin_save_expr (len);
   4202  1.1  mrg 
   4203  1.1  mrg   len_rtx = expand_normal (len);
   4204  1.1  mrg   determine_block_size (len, len_rtx, &min_size, &max_size,
   4205  1.1  mrg 			&probable_max_size);
   4206  1.1  mrg   dest_mem = get_memory_rtx (dest, len);
   4207  1.1  mrg   val_mode = TYPE_MODE (unsigned_char_type_node);
   4208  1.1  mrg 
   4209  1.1  mrg   if (TREE_CODE (val) != INTEGER_CST
   4210  1.1  mrg       || target_char_cast (val, &c))
   4211  1.1  mrg     {
   4212  1.1  mrg       rtx val_rtx;
   4213  1.1  mrg 
   4214  1.1  mrg       val_rtx = expand_normal (val);
   4215  1.1  mrg       val_rtx = convert_to_mode (val_mode, val_rtx, 0);
   4216  1.1  mrg 
   4217  1.1  mrg       /* Assume that we can memset by pieces if we can store
   4218  1.1  mrg        * the coefficients by pieces (in the required modes).
   4219  1.1  mrg        * We can't pass builtin_memset_gen_str as that emits RTL.  */
   4220  1.1  mrg       c = 1;
   4221  1.1  mrg       if (tree_fits_uhwi_p (len)
   4222  1.1  mrg 	  && can_store_by_pieces (tree_to_uhwi (len),
   4223  1.1  mrg 				  builtin_memset_read_str, &c, dest_align,
   4224  1.1  mrg 				  true))
   4225  1.1  mrg 	{
   4226  1.1  mrg 	  val_rtx = force_reg (val_mode, val_rtx);
   4227  1.1  mrg 	  store_by_pieces (dest_mem, tree_to_uhwi (len),
   4228  1.1  mrg 			   builtin_memset_gen_str, val_rtx, dest_align,
   4229  1.1  mrg 			   true, RETURN_BEGIN);
   4230  1.1  mrg 	}
   4231  1.1  mrg       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
   4232  1.1  mrg 					dest_align, expected_align,
   4233  1.1  mrg 					expected_size, min_size, max_size,
   4234  1.1  mrg 					probable_max_size)
   4235  1.1  mrg 	       && !try_store_by_multiple_pieces (dest_mem, len_rtx,
   4236  1.1  mrg 						 tree_ctz (len),
   4237  1.1  mrg 						 min_size, max_size,
   4238  1.1  mrg 						 val_rtx, 0,
   4239  1.1  mrg 						 dest_align))
   4240  1.1  mrg 	goto do_libcall;
   4241  1.1  mrg 
   4242  1.1  mrg       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
   4243  1.1  mrg       dest_mem = convert_memory_address (ptr_mode, dest_mem);
   4244  1.1  mrg       return dest_mem;
   4245  1.1  mrg     }
   4246  1.1  mrg 
   4247  1.1  mrg   if (c)
   4248  1.1  mrg     {
   4249  1.1  mrg       if (tree_fits_uhwi_p (len)
   4250  1.1  mrg 	  && can_store_by_pieces (tree_to_uhwi (len),
   4251  1.1  mrg 				  builtin_memset_read_str, &c, dest_align,
   4252  1.1  mrg 				  true))
   4253  1.1  mrg 	store_by_pieces (dest_mem, tree_to_uhwi (len),
   4254  1.1  mrg 			 builtin_memset_read_str, &c, dest_align, true,
   4255  1.1  mrg 			 RETURN_BEGIN);
   4256  1.1  mrg       else if (!set_storage_via_setmem (dest_mem, len_rtx,
   4257  1.1  mrg 					gen_int_mode (c, val_mode),
   4258  1.1  mrg 					dest_align, expected_align,
   4259  1.1  mrg 					expected_size, min_size, max_size,
   4260  1.1  mrg 					probable_max_size)
   4261  1.1  mrg 	       && !try_store_by_multiple_pieces (dest_mem, len_rtx,
   4262  1.1  mrg 						 tree_ctz (len),
   4263  1.1  mrg 						 min_size, max_size,
   4264  1.1  mrg 						 NULL_RTX, c,
   4265  1.1  mrg 						 dest_align))
   4266  1.1  mrg 	goto do_libcall;
   4267  1.1  mrg 
   4268  1.1  mrg       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
   4269  1.1  mrg       dest_mem = convert_memory_address (ptr_mode, dest_mem);
   4270  1.1  mrg       return dest_mem;
   4271  1.1  mrg     }
   4272  1.1  mrg 
   4273  1.1  mrg   set_mem_align (dest_mem, dest_align);
   4274  1.1  mrg   dest_addr = clear_storage_hints (dest_mem, len_rtx,
   4275  1.1  mrg 				   CALL_EXPR_TAILCALL (orig_exp)
   4276  1.1  mrg 				   ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
   4277  1.1  mrg 				   expected_align, expected_size,
   4278  1.1  mrg 				   min_size, max_size,
   4279  1.1  mrg 				   probable_max_size, tree_ctz (len));
   4280  1.1  mrg 
   4281  1.1  mrg   if (dest_addr == 0)
   4282  1.1  mrg     {
   4283  1.1  mrg       dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
   4284  1.1  mrg       dest_addr = convert_memory_address (ptr_mode, dest_addr);
   4285  1.1  mrg     }
   4286  1.1  mrg 
   4287  1.1  mrg   return dest_addr;
   4288  1.1  mrg 
   4289  1.1  mrg  do_libcall:
   4290  1.1  mrg   fndecl = get_callee_fndecl (orig_exp);
   4291  1.1  mrg   fcode = DECL_FUNCTION_CODE (fndecl);
   4292  1.1  mrg   if (fcode == BUILT_IN_MEMSET)
   4293  1.1  mrg     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
   4294  1.1  mrg 				dest, val, len);
   4295  1.1  mrg   else if (fcode == BUILT_IN_BZERO)
   4296  1.1  mrg     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
   4297  1.1  mrg 				dest, len);
   4298  1.1  mrg   else
   4299  1.1  mrg     gcc_unreachable ();
   4300  1.1  mrg   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   4301  1.1  mrg   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
   4302  1.1  mrg   return expand_call (fn, target, target == const0_rtx);
   4303  1.1  mrg }
   4304  1.1  mrg 
   4305  1.1  mrg /* Expand expression EXP, which is a call to the bzero builtin.  Return
   4306  1.1  mrg    NULL_RTX if we failed the caller should emit a normal call.  */
   4307  1.1  mrg 
   4308  1.1  mrg static rtx
   4309  1.1  mrg expand_builtin_bzero (tree exp)
   4310  1.1  mrg {
   4311  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   4312  1.1  mrg     return NULL_RTX;
   4313  1.1  mrg 
   4314  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   4315  1.1  mrg   tree size = CALL_EXPR_ARG (exp, 1);
   4316  1.1  mrg 
   4317  1.1  mrg   /* New argument list transforming bzero(ptr x, int y) to
   4318  1.1  mrg      memset(ptr x, int 0, size_t y).   This is done this way
   4319  1.1  mrg      so that if it isn't expanded inline, we fallback to
   4320  1.1  mrg      calling bzero instead of memset.  */
   4321  1.1  mrg 
   4322  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   4323  1.1  mrg 
   4324  1.1  mrg   return expand_builtin_memset_args (dest, integer_zero_node,
   4325  1.1  mrg 				     fold_convert_loc (loc,
   4326  1.1  mrg 						       size_type_node, size),
   4327  1.1  mrg 				     const0_rtx, VOIDmode, exp);
   4328  1.1  mrg }
   4329  1.1  mrg 
   4330  1.1  mrg /* Try to expand cmpstr operation ICODE with the given operands.
   4331  1.1  mrg    Return the result rtx on success, otherwise return null.  */
   4332  1.1  mrg 
   4333  1.1  mrg static rtx
   4334  1.1  mrg expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
   4335  1.1  mrg 	       HOST_WIDE_INT align)
   4336  1.1  mrg {
   4337  1.1  mrg   machine_mode insn_mode = insn_data[icode].operand[0].mode;
   4338  1.1  mrg 
   4339  1.1  mrg   if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
   4340  1.1  mrg     target = NULL_RTX;
   4341  1.1  mrg 
   4342  1.1  mrg   class expand_operand ops[4];
   4343  1.1  mrg   create_output_operand (&ops[0], target, insn_mode);
   4344  1.1  mrg   create_fixed_operand (&ops[1], arg1_rtx);
   4345  1.1  mrg   create_fixed_operand (&ops[2], arg2_rtx);
   4346  1.1  mrg   create_integer_operand (&ops[3], align);
   4347  1.1  mrg   if (maybe_expand_insn (icode, 4, ops))
   4348  1.1  mrg     return ops[0].value;
   4349  1.1  mrg   return NULL_RTX;
   4350  1.1  mrg }
   4351  1.1  mrg 
   4352  1.1  mrg /* Expand expression EXP, which is a call to the memcmp built-in function.
   4353  1.1  mrg    Return NULL_RTX if we failed and the caller should emit a normal call,
   4354  1.1  mrg    otherwise try to get the result in TARGET, if convenient.
   4355  1.1  mrg    RESULT_EQ is true if we can relax the returned value to be either zero
   4356  1.1  mrg    or nonzero, without caring about the sign.  */
   4357  1.1  mrg 
   4358  1.1  mrg static rtx
   4359  1.1  mrg expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
   4360  1.1  mrg {
   4361  1.1  mrg   if (!validate_arglist (exp,
   4362  1.1  mrg  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   4363  1.1  mrg     return NULL_RTX;
   4364  1.1  mrg 
   4365  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 0);
   4366  1.1  mrg   tree arg2 = CALL_EXPR_ARG (exp, 1);
   4367  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   4368  1.1  mrg 
   4369  1.1  mrg   /* Due to the performance benefit, always inline the calls first
   4370  1.1  mrg      when result_eq is false.  */
   4371  1.1  mrg   rtx result = NULL_RTX;
   4372  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
   4373  1.1  mrg   if (!result_eq && fcode != BUILT_IN_BCMP)
   4374  1.1  mrg     {
   4375  1.1  mrg       result = inline_expand_builtin_bytecmp (exp, target);
   4376  1.1  mrg       if (result)
   4377  1.1  mrg 	return result;
   4378  1.1  mrg     }
   4379  1.1  mrg 
   4380  1.1  mrg   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   4381  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   4382  1.1  mrg 
   4383  1.1  mrg   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
   4384  1.1  mrg   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
   4385  1.1  mrg 
   4386  1.1  mrg   /* If we don't have POINTER_TYPE, call the function.  */
   4387  1.1  mrg   if (arg1_align == 0 || arg2_align == 0)
   4388  1.1  mrg     return NULL_RTX;
   4389  1.1  mrg 
   4390  1.1  mrg   rtx arg1_rtx = get_memory_rtx (arg1, len);
   4391  1.1  mrg   rtx arg2_rtx = get_memory_rtx (arg2, len);
   4392  1.1  mrg   rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
   4393  1.1  mrg 
   4394  1.1  mrg   /* Set MEM_SIZE as appropriate.  */
   4395  1.1  mrg   if (CONST_INT_P (len_rtx))
   4396  1.1  mrg     {
   4397  1.1  mrg       set_mem_size (arg1_rtx, INTVAL (len_rtx));
   4398  1.1  mrg       set_mem_size (arg2_rtx, INTVAL (len_rtx));
   4399  1.1  mrg     }
   4400  1.1  mrg 
   4401  1.1  mrg   by_pieces_constfn constfn = NULL;
   4402  1.1  mrg 
   4403  1.1  mrg   /* Try to get the byte representation of the constant ARG2 (or, only
   4404  1.1  mrg      when the function's result is used for equality to zero, ARG1)
   4405  1.1  mrg      points to, with its byte size in NBYTES.  */
   4406  1.1  mrg   unsigned HOST_WIDE_INT nbytes;
   4407  1.1  mrg   const char *rep = getbyterep (arg2, &nbytes);
   4408  1.1  mrg   if (result_eq && rep == NULL)
   4409  1.1  mrg     {
   4410  1.1  mrg       /* For equality to zero the arguments are interchangeable.  */
   4411  1.1  mrg       rep = getbyterep (arg1, &nbytes);
   4412  1.1  mrg       if (rep != NULL)
   4413  1.1  mrg 	std::swap (arg1_rtx, arg2_rtx);
   4414  1.1  mrg     }
   4415  1.1  mrg 
   4416  1.1  mrg   /* If the function's constant bound LEN_RTX is less than or equal
   4417  1.1  mrg      to the byte size of the representation of the constant argument,
   4418  1.1  mrg      and if block move would be done by pieces, we can avoid loading
   4419  1.1  mrg      the bytes from memory and only store the computed constant result.  */
   4420  1.1  mrg   if (rep
   4421  1.1  mrg       && CONST_INT_P (len_rtx)
   4422  1.1  mrg       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
   4423  1.1  mrg     constfn = builtin_memcpy_read_str;
   4424  1.1  mrg 
   4425  1.1  mrg   result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
   4426  1.1  mrg 				 TREE_TYPE (len), target,
   4427  1.1  mrg 				 result_eq, constfn,
   4428  1.1  mrg 				 CONST_CAST (char *, rep));
   4429  1.1  mrg 
   4430  1.1  mrg   if (result)
   4431  1.1  mrg     {
   4432  1.1  mrg       /* Return the value in the proper mode for this function.  */
   4433  1.1  mrg       if (GET_MODE (result) == mode)
   4434  1.1  mrg 	return result;
   4435  1.1  mrg 
   4436  1.1  mrg       if (target != 0)
   4437  1.1  mrg 	{
   4438  1.1  mrg 	  convert_move (target, result, 0);
   4439  1.1  mrg 	  return target;
   4440  1.1  mrg 	}
   4441  1.1  mrg 
   4442  1.1  mrg       return convert_to_mode (mode, result, 0);
   4443  1.1  mrg     }
   4444  1.1  mrg 
   4445  1.1  mrg   return NULL_RTX;
   4446  1.1  mrg }
   4447  1.1  mrg 
   4448  1.1  mrg /* Expand expression EXP, which is a call to the strcmp builtin.  Return NULL_RTX
   4449  1.1  mrg    if we failed the caller should emit a normal call, otherwise try to get
   4450  1.1  mrg    the result in TARGET, if convenient.  */
   4451  1.1  mrg 
   4452  1.1  mrg static rtx
   4453  1.1  mrg expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
   4454  1.1  mrg {
   4455  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   4456  1.1  mrg     return NULL_RTX;
   4457  1.1  mrg 
   4458  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 0);
   4459  1.1  mrg   tree arg2 = CALL_EXPR_ARG (exp, 1);
   4460  1.1  mrg 
   4461  1.1  mrg   /* Due to the performance benefit, always inline the calls first.  */
   4462  1.1  mrg   rtx result = NULL_RTX;
   4463  1.1  mrg   result = inline_expand_builtin_bytecmp (exp, target);
   4464  1.1  mrg   if (result)
   4465  1.1  mrg     return result;
   4466  1.1  mrg 
   4467  1.1  mrg   insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
   4468  1.1  mrg   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
   4469  1.1  mrg   if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
   4470  1.1  mrg     return NULL_RTX;
   4471  1.1  mrg 
   4472  1.1  mrg   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
   4473  1.1  mrg   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
   4474  1.1  mrg 
   4475  1.1  mrg   /* If we don't have POINTER_TYPE, call the function.  */
   4476  1.1  mrg   if (arg1_align == 0 || arg2_align == 0)
   4477  1.1  mrg     return NULL_RTX;
   4478  1.1  mrg 
   4479  1.1  mrg   /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
   4480  1.1  mrg   arg1 = builtin_save_expr (arg1);
   4481  1.1  mrg   arg2 = builtin_save_expr (arg2);
   4482  1.1  mrg 
   4483  1.1  mrg   rtx arg1_rtx = get_memory_rtx (arg1, NULL);
   4484  1.1  mrg   rtx arg2_rtx = get_memory_rtx (arg2, NULL);
   4485  1.1  mrg 
   4486  1.1  mrg   /* Try to call cmpstrsi.  */
   4487  1.1  mrg   if (cmpstr_icode != CODE_FOR_nothing)
   4488  1.1  mrg     result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
   4489  1.1  mrg 			    MIN (arg1_align, arg2_align));
   4490  1.1  mrg 
   4491  1.1  mrg   /* Try to determine at least one length and call cmpstrnsi.  */
   4492  1.1  mrg   if (!result && cmpstrn_icode != CODE_FOR_nothing)
   4493  1.1  mrg     {
   4494  1.1  mrg       tree len;
   4495  1.1  mrg       rtx arg3_rtx;
   4496  1.1  mrg 
   4497  1.1  mrg       tree len1 = c_strlen (arg1, 1);
   4498  1.1  mrg       tree len2 = c_strlen (arg2, 1);
   4499  1.1  mrg 
   4500  1.1  mrg       if (len1)
   4501  1.1  mrg 	len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
   4502  1.1  mrg       if (len2)
   4503  1.1  mrg 	len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
   4504  1.1  mrg 
   4505  1.1  mrg       /* If we don't have a constant length for the first, use the length
   4506  1.1  mrg 	 of the second, if we know it.  We don't require a constant for
   4507  1.1  mrg 	 this case; some cost analysis could be done if both are available
   4508  1.1  mrg 	 but neither is constant.  For now, assume they're equally cheap,
   4509  1.1  mrg 	 unless one has side effects.  If both strings have constant lengths,
   4510  1.1  mrg 	 use the smaller.  */
   4511  1.1  mrg 
   4512  1.1  mrg       if (!len1)
   4513  1.1  mrg 	len = len2;
   4514  1.1  mrg       else if (!len2)
   4515  1.1  mrg 	len = len1;
   4516  1.1  mrg       else if (TREE_SIDE_EFFECTS (len1))
   4517  1.1  mrg 	len = len2;
   4518  1.1  mrg       else if (TREE_SIDE_EFFECTS (len2))
   4519  1.1  mrg 	len = len1;
   4520  1.1  mrg       else if (TREE_CODE (len1) != INTEGER_CST)
   4521  1.1  mrg 	len = len2;
   4522  1.1  mrg       else if (TREE_CODE (len2) != INTEGER_CST)
   4523  1.1  mrg 	len = len1;
   4524  1.1  mrg       else if (tree_int_cst_lt (len1, len2))
   4525  1.1  mrg 	len = len1;
   4526  1.1  mrg       else
   4527  1.1  mrg 	len = len2;
   4528  1.1  mrg 
   4529  1.1  mrg       /* If both arguments have side effects, we cannot optimize.  */
   4530  1.1  mrg       if (len && !TREE_SIDE_EFFECTS (len))
   4531  1.1  mrg 	{
   4532  1.1  mrg 	  arg3_rtx = expand_normal (len);
   4533  1.1  mrg 	  result = expand_cmpstrn_or_cmpmem
   4534  1.1  mrg 	    (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
   4535  1.1  mrg 	     arg3_rtx, MIN (arg1_align, arg2_align));
   4536  1.1  mrg 	}
   4537  1.1  mrg     }
   4538  1.1  mrg 
   4539  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   4540  1.1  mrg   if (result)
   4541  1.1  mrg     {
   4542  1.1  mrg       /* Return the value in the proper mode for this function.  */
   4543  1.1  mrg       machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   4544  1.1  mrg       if (GET_MODE (result) == mode)
   4545  1.1  mrg 	return result;
   4546  1.1  mrg       if (target == 0)
   4547  1.1  mrg 	return convert_to_mode (mode, result, 0);
   4548  1.1  mrg       convert_move (target, result, 0);
   4549  1.1  mrg       return target;
   4550  1.1  mrg     }
   4551  1.1  mrg 
   4552  1.1  mrg   /* Expand the library call ourselves using a stabilized argument
   4553  1.1  mrg      list to avoid re-evaluating the function's arguments twice.  */
   4554  1.1  mrg   tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
   4555  1.1  mrg   copy_warning (fn, exp);
   4556  1.1  mrg   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   4557  1.1  mrg   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   4558  1.1  mrg   return expand_call (fn, target, target == const0_rtx);
   4559  1.1  mrg }
   4560  1.1  mrg 
   4561  1.1  mrg /* Expand expression EXP, which is a call to the strncmp builtin. Return
   4562  1.1  mrg    NULL_RTX if we failed the caller should emit a normal call, otherwise
   4563  1.1  mrg    try to get the result in TARGET, if convenient.  */
   4564  1.1  mrg 
   4565  1.1  mrg static rtx
   4566  1.1  mrg expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
   4567  1.1  mrg 			ATTRIBUTE_UNUSED machine_mode mode)
   4568  1.1  mrg {
   4569  1.1  mrg   if (!validate_arglist (exp,
   4570  1.1  mrg  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   4571  1.1  mrg     return NULL_RTX;
   4572  1.1  mrg 
   4573  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 0);
   4574  1.1  mrg   tree arg2 = CALL_EXPR_ARG (exp, 1);
   4575  1.1  mrg   tree arg3 = CALL_EXPR_ARG (exp, 2);
   4576  1.1  mrg 
   4577  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   4578  1.1  mrg   tree len1 = c_strlen (arg1, 1);
   4579  1.1  mrg   tree len2 = c_strlen (arg2, 1);
   4580  1.1  mrg 
   4581  1.1  mrg   /* Due to the performance benefit, always inline the calls first.  */
   4582  1.1  mrg   rtx result = NULL_RTX;
   4583  1.1  mrg   result = inline_expand_builtin_bytecmp (exp, target);
   4584  1.1  mrg   if (result)
   4585  1.1  mrg     return result;
   4586  1.1  mrg 
   4587  1.1  mrg   /* If c_strlen can determine an expression for one of the string
   4588  1.1  mrg      lengths, and it doesn't have side effects, then emit cmpstrnsi
   4589  1.1  mrg      using length MIN(strlen(string)+1, arg3).  */
   4590  1.1  mrg   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
   4591  1.1  mrg   if (cmpstrn_icode == CODE_FOR_nothing)
   4592  1.1  mrg     return NULL_RTX;
   4593  1.1  mrg 
   4594  1.1  mrg   tree len;
   4595  1.1  mrg 
   4596  1.1  mrg   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
   4597  1.1  mrg   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
   4598  1.1  mrg 
   4599  1.1  mrg   if (len1)
   4600  1.1  mrg     len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
   4601  1.1  mrg   if (len2)
   4602  1.1  mrg     len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
   4603  1.1  mrg 
   4604  1.1  mrg   tree len3 = fold_convert_loc (loc, sizetype, arg3);
   4605  1.1  mrg 
   4606  1.1  mrg   /* If we don't have a constant length for the first, use the length
   4607  1.1  mrg      of the second, if we know it.  If neither string is constant length,
   4608  1.1  mrg      use the given length argument.  We don't require a constant for
   4609  1.1  mrg      this case; some cost analysis could be done if both are available
   4610  1.1  mrg      but neither is constant.  For now, assume they're equally cheap,
   4611  1.1  mrg      unless one has side effects.  If both strings have constant lengths,
   4612  1.1  mrg      use the smaller.  */
   4613  1.1  mrg 
   4614  1.1  mrg   if (!len1 && !len2)
   4615  1.1  mrg     len = len3;
   4616  1.1  mrg   else if (!len1)
   4617  1.1  mrg     len = len2;
   4618  1.1  mrg   else if (!len2)
   4619  1.1  mrg     len = len1;
   4620  1.1  mrg   else if (TREE_SIDE_EFFECTS (len1))
   4621  1.1  mrg     len = len2;
   4622  1.1  mrg   else if (TREE_SIDE_EFFECTS (len2))
   4623  1.1  mrg     len = len1;
   4624  1.1  mrg   else if (TREE_CODE (len1) != INTEGER_CST)
   4625  1.1  mrg     len = len2;
   4626  1.1  mrg   else if (TREE_CODE (len2) != INTEGER_CST)
   4627  1.1  mrg     len = len1;
   4628  1.1  mrg   else if (tree_int_cst_lt (len1, len2))
   4629  1.1  mrg     len = len1;
   4630  1.1  mrg   else
   4631  1.1  mrg     len = len2;
   4632  1.1  mrg 
   4633  1.1  mrg   /* If we are not using the given length, we must incorporate it here.
   4634  1.1  mrg      The actual new length parameter will be MIN(len,arg3) in this case.  */
   4635  1.1  mrg   if (len != len3)
   4636  1.1  mrg     {
   4637  1.1  mrg       len = fold_convert_loc (loc, sizetype, len);
   4638  1.1  mrg       len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
   4639  1.1  mrg     }
   4640  1.1  mrg   rtx arg1_rtx = get_memory_rtx (arg1, len);
   4641  1.1  mrg   rtx arg2_rtx = get_memory_rtx (arg2, len);
   4642  1.1  mrg   rtx arg3_rtx = expand_normal (len);
   4643  1.1  mrg   result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
   4644  1.1  mrg 				     arg2_rtx, TREE_TYPE (len), arg3_rtx,
   4645  1.1  mrg 				     MIN (arg1_align, arg2_align));
   4646  1.1  mrg 
   4647  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   4648  1.1  mrg   if (result)
   4649  1.1  mrg     {
   4650  1.1  mrg       /* Return the value in the proper mode for this function.  */
   4651  1.1  mrg       mode = TYPE_MODE (TREE_TYPE (exp));
   4652  1.1  mrg       if (GET_MODE (result) == mode)
   4653  1.1  mrg 	return result;
   4654  1.1  mrg       if (target == 0)
   4655  1.1  mrg 	return convert_to_mode (mode, result, 0);
   4656  1.1  mrg       convert_move (target, result, 0);
   4657  1.1  mrg       return target;
   4658  1.1  mrg     }
   4659  1.1  mrg 
   4660  1.1  mrg   /* Expand the library call ourselves using a stabilized argument
   4661  1.1  mrg      list to avoid re-evaluating the function's arguments twice.  */
   4662  1.1  mrg   tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
   4663  1.1  mrg   copy_warning (call, exp);
   4664  1.1  mrg   gcc_assert (TREE_CODE (call) == CALL_EXPR);
   4665  1.1  mrg   CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
   4666  1.1  mrg   return expand_call (call, target, target == const0_rtx);
   4667  1.1  mrg }
   4668  1.1  mrg 
   4669  1.1  mrg /* Expand a call to __builtin_saveregs, generating the result in TARGET,
   4670  1.1  mrg    if that's convenient.  */
   4671  1.1  mrg 
   4672  1.1  mrg rtx
   4673  1.1  mrg expand_builtin_saveregs (void)
   4674  1.1  mrg {
   4675  1.1  mrg   rtx val;
   4676  1.1  mrg   rtx_insn *seq;
   4677  1.1  mrg 
   4678  1.1  mrg   /* Don't do __builtin_saveregs more than once in a function.
   4679  1.1  mrg      Save the result of the first call and reuse it.  */
   4680  1.1  mrg   if (saveregs_value != 0)
   4681  1.1  mrg     return saveregs_value;
   4682  1.1  mrg 
   4683  1.1  mrg   /* When this function is called, it means that registers must be
   4684  1.1  mrg      saved on entry to this function.  So we migrate the call to the
   4685  1.1  mrg      first insn of this function.  */
   4686  1.1  mrg 
   4687  1.1  mrg   start_sequence ();
   4688  1.1  mrg 
   4689  1.1  mrg   /* Do whatever the machine needs done in this case.  */
   4690  1.1  mrg   val = targetm.calls.expand_builtin_saveregs ();
   4691  1.1  mrg 
   4692  1.1  mrg   seq = get_insns ();
   4693  1.1  mrg   end_sequence ();
   4694  1.1  mrg 
   4695  1.1  mrg   saveregs_value = val;
   4696  1.1  mrg 
   4697  1.1  mrg   /* Put the insns after the NOTE that starts the function.  If this
   4698  1.1  mrg      is inside a start_sequence, make the outer-level insn chain current, so
   4699  1.1  mrg      the code is placed at the start of the function.  */
   4700  1.1  mrg   push_topmost_sequence ();
   4701  1.1  mrg   emit_insn_after (seq, entry_of_function ());
   4702  1.1  mrg   pop_topmost_sequence ();
   4703  1.1  mrg 
   4704  1.1  mrg   return val;
   4705  1.1  mrg }
   4706  1.1  mrg 
   4707  1.1  mrg /* Expand a call to __builtin_next_arg.  */
   4708  1.1  mrg 
   4709  1.1  mrg static rtx
   4710  1.1  mrg expand_builtin_next_arg (void)
   4711  1.1  mrg {
   4712  1.1  mrg   /* Checking arguments is already done in fold_builtin_next_arg
   4713  1.1  mrg      that must be called before this function.  */
   4714  1.1  mrg   return expand_binop (ptr_mode, add_optab,
   4715  1.1  mrg 		       crtl->args.internal_arg_pointer,
   4716  1.1  mrg 		       crtl->args.arg_offset_rtx,
   4717  1.1  mrg 		       NULL_RTX, 0, OPTAB_LIB_WIDEN);
   4718  1.1  mrg }
   4719  1.1  mrg 
   4720  1.1  mrg /* Make it easier for the backends by protecting the valist argument
   4721  1.1  mrg    from multiple evaluations.  */
   4722  1.1  mrg 
   4723  1.1  mrg static tree
   4724  1.1  mrg stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
   4725  1.1  mrg {
   4726  1.1  mrg   tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
   4727  1.1  mrg 
   4728  1.1  mrg   /* The current way of determining the type of valist is completely
   4729  1.1  mrg      bogus.  We should have the information on the va builtin instead.  */
   4730  1.1  mrg   if (!vatype)
   4731  1.1  mrg     vatype = targetm.fn_abi_va_list (cfun->decl);
   4732  1.1  mrg 
   4733  1.1  mrg   if (TREE_CODE (vatype) == ARRAY_TYPE)
   4734  1.1  mrg     {
   4735  1.1  mrg       if (TREE_SIDE_EFFECTS (valist))
   4736  1.1  mrg 	valist = save_expr (valist);
   4737  1.1  mrg 
   4738  1.1  mrg       /* For this case, the backends will be expecting a pointer to
   4739  1.1  mrg 	 vatype, but it's possible we've actually been given an array
   4740  1.1  mrg 	 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
   4741  1.1  mrg 	 So fix it.  */
   4742  1.1  mrg       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
   4743  1.1  mrg 	{
   4744  1.1  mrg 	  tree p1 = build_pointer_type (TREE_TYPE (vatype));
   4745  1.1  mrg 	  valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
   4746  1.1  mrg 	}
   4747  1.1  mrg     }
   4748  1.1  mrg   else
   4749  1.1  mrg     {
   4750  1.1  mrg       tree pt = build_pointer_type (vatype);
   4751  1.1  mrg 
   4752  1.1  mrg       if (! needs_lvalue)
   4753  1.1  mrg 	{
   4754  1.1  mrg 	  if (! TREE_SIDE_EFFECTS (valist))
   4755  1.1  mrg 	    return valist;
   4756  1.1  mrg 
   4757  1.1  mrg 	  valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
   4758  1.1  mrg 	  TREE_SIDE_EFFECTS (valist) = 1;
   4759  1.1  mrg 	}
   4760  1.1  mrg 
   4761  1.1  mrg       if (TREE_SIDE_EFFECTS (valist))
   4762  1.1  mrg 	valist = save_expr (valist);
   4763  1.1  mrg       valist = fold_build2_loc (loc, MEM_REF,
   4764  1.1  mrg 				vatype, valist, build_int_cst (pt, 0));
   4765  1.1  mrg     }
   4766  1.1  mrg 
   4767  1.1  mrg   return valist;
   4768  1.1  mrg }
   4769  1.1  mrg 
   4770  1.1  mrg /* The "standard" definition of va_list is void*.  */
   4771  1.1  mrg 
   4772  1.1  mrg tree
   4773  1.1  mrg std_build_builtin_va_list (void)
   4774  1.1  mrg {
   4775  1.1  mrg   return ptr_type_node;
   4776  1.1  mrg }
   4777  1.1  mrg 
   4778  1.1  mrg /* The "standard" abi va_list is va_list_type_node.  */
   4779  1.1  mrg 
   4780  1.1  mrg tree
   4781  1.1  mrg std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
   4782  1.1  mrg {
   4783  1.1  mrg   return va_list_type_node;
   4784  1.1  mrg }
   4785  1.1  mrg 
   4786  1.1  mrg /* The "standard" type of va_list is va_list_type_node.  */
   4787  1.1  mrg 
   4788  1.1  mrg tree
   4789  1.1  mrg std_canonical_va_list_type (tree type)
   4790  1.1  mrg {
   4791  1.1  mrg   tree wtype, htype;
   4792  1.1  mrg 
   4793  1.1  mrg   wtype = va_list_type_node;
   4794  1.1  mrg   htype = type;
   4795  1.1  mrg 
   4796  1.1  mrg   if (TREE_CODE (wtype) == ARRAY_TYPE)
   4797  1.1  mrg     {
   4798  1.1  mrg       /* If va_list is an array type, the argument may have decayed
   4799  1.1  mrg 	 to a pointer type, e.g. by being passed to another function.
   4800  1.1  mrg 	 In that case, unwrap both types so that we can compare the
   4801  1.1  mrg 	 underlying records.  */
   4802  1.1  mrg       if (TREE_CODE (htype) == ARRAY_TYPE
   4803  1.1  mrg 	  || POINTER_TYPE_P (htype))
   4804  1.1  mrg 	{
   4805  1.1  mrg 	  wtype = TREE_TYPE (wtype);
   4806  1.1  mrg 	  htype = TREE_TYPE (htype);
   4807  1.1  mrg 	}
   4808  1.1  mrg     }
   4809  1.1  mrg   if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
   4810  1.1  mrg     return va_list_type_node;
   4811  1.1  mrg 
   4812  1.1  mrg   return NULL_TREE;
   4813  1.1  mrg }
   4814  1.1  mrg 
   4815  1.1  mrg /* The "standard" implementation of va_start: just assign `nextarg' to
   4816  1.1  mrg    the variable.  */
   4817  1.1  mrg 
   4818  1.1  mrg void
   4819  1.1  mrg std_expand_builtin_va_start (tree valist, rtx nextarg)
   4820  1.1  mrg {
   4821  1.1  mrg   rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
   4822  1.1  mrg   convert_move (va_r, nextarg, 0);
   4823  1.1  mrg }
   4824  1.1  mrg 
   4825  1.1  mrg /* Expand EXP, a call to __builtin_va_start.  */
   4826  1.1  mrg 
   4827  1.1  mrg static rtx
   4828  1.1  mrg expand_builtin_va_start (tree exp)
   4829  1.1  mrg {
   4830  1.1  mrg   rtx nextarg;
   4831  1.1  mrg   tree valist;
   4832  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   4833  1.1  mrg 
   4834  1.1  mrg   if (call_expr_nargs (exp) < 2)
   4835  1.1  mrg     {
   4836  1.1  mrg       error_at (loc, "too few arguments to function %<va_start%>");
   4837  1.1  mrg       return const0_rtx;
   4838  1.1  mrg     }
   4839  1.1  mrg 
   4840  1.1  mrg   if (fold_builtin_next_arg (exp, true))
   4841  1.1  mrg     return const0_rtx;
   4842  1.1  mrg 
   4843  1.1  mrg   nextarg = expand_builtin_next_arg ();
   4844  1.1  mrg   valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
   4845  1.1  mrg 
   4846  1.1  mrg   if (targetm.expand_builtin_va_start)
   4847  1.1  mrg     targetm.expand_builtin_va_start (valist, nextarg);
   4848  1.1  mrg   else
   4849  1.1  mrg     std_expand_builtin_va_start (valist, nextarg);
   4850  1.1  mrg 
   4851  1.1  mrg   return const0_rtx;
   4852  1.1  mrg }
   4853  1.1  mrg 
   4854  1.1  mrg /* Expand EXP, a call to __builtin_va_end.  */
   4855  1.1  mrg 
   4856  1.1  mrg static rtx
   4857  1.1  mrg expand_builtin_va_end (tree exp)
   4858  1.1  mrg {
   4859  1.1  mrg   tree valist = CALL_EXPR_ARG (exp, 0);
   4860  1.1  mrg 
   4861  1.1  mrg   /* Evaluate for side effects, if needed.  I hate macros that don't
   4862  1.1  mrg      do that.  */
   4863  1.1  mrg   if (TREE_SIDE_EFFECTS (valist))
   4864  1.1  mrg     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
   4865  1.1  mrg 
   4866  1.1  mrg   return const0_rtx;
   4867  1.1  mrg }
   4868  1.1  mrg 
   4869  1.1  mrg /* Expand EXP, a call to __builtin_va_copy.  We do this as a
   4870  1.1  mrg    builtin rather than just as an assignment in stdarg.h because of the
   4871  1.1  mrg    nastiness of array-type va_list types.  */
   4872  1.1  mrg 
   4873  1.1  mrg static rtx
   4874  1.1  mrg expand_builtin_va_copy (tree exp)
   4875  1.1  mrg {
   4876  1.1  mrg   tree dst, src, t;
   4877  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   4878  1.1  mrg 
   4879  1.1  mrg   dst = CALL_EXPR_ARG (exp, 0);
   4880  1.1  mrg   src = CALL_EXPR_ARG (exp, 1);
   4881  1.1  mrg 
   4882  1.1  mrg   dst = stabilize_va_list_loc (loc, dst, 1);
   4883  1.1  mrg   src = stabilize_va_list_loc (loc, src, 0);
   4884  1.1  mrg 
   4885  1.1  mrg   gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
   4886  1.1  mrg 
   4887  1.1  mrg   if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
   4888  1.1  mrg     {
   4889  1.1  mrg       t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
   4890  1.1  mrg       TREE_SIDE_EFFECTS (t) = 1;
   4891  1.1  mrg       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
   4892  1.1  mrg     }
   4893  1.1  mrg   else
   4894  1.1  mrg     {
   4895  1.1  mrg       rtx dstb, srcb, size;
   4896  1.1  mrg 
   4897  1.1  mrg       /* Evaluate to pointers.  */
   4898  1.1  mrg       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
   4899  1.1  mrg       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
   4900  1.1  mrg       size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
   4901  1.1  mrg       		  NULL_RTX, VOIDmode, EXPAND_NORMAL);
   4902  1.1  mrg 
   4903  1.1  mrg       dstb = convert_memory_address (Pmode, dstb);
   4904  1.1  mrg       srcb = convert_memory_address (Pmode, srcb);
   4905  1.1  mrg 
   4906  1.1  mrg       /* "Dereference" to BLKmode memories.  */
   4907  1.1  mrg       dstb = gen_rtx_MEM (BLKmode, dstb);
   4908  1.1  mrg       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
   4909  1.1  mrg       set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
   4910  1.1  mrg       srcb = gen_rtx_MEM (BLKmode, srcb);
   4911  1.1  mrg       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
   4912  1.1  mrg       set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
   4913  1.1  mrg 
   4914  1.1  mrg       /* Copy.  */
   4915  1.1  mrg       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
   4916  1.1  mrg     }
   4917  1.1  mrg 
   4918  1.1  mrg   return const0_rtx;
   4919  1.1  mrg }
   4920  1.1  mrg 
   4921  1.1  mrg /* Expand a call to one of the builtin functions __builtin_frame_address or
   4922  1.1  mrg    __builtin_return_address.  */
   4923  1.1  mrg 
   4924  1.1  mrg static rtx
   4925  1.1  mrg expand_builtin_frame_address (tree fndecl, tree exp)
   4926  1.1  mrg {
   4927  1.1  mrg   /* The argument must be a nonnegative integer constant.
   4928  1.1  mrg      It counts the number of frames to scan up the stack.
   4929  1.1  mrg      The value is either the frame pointer value or the return
   4930  1.1  mrg      address saved in that frame.  */
   4931  1.1  mrg   if (call_expr_nargs (exp) == 0)
   4932  1.1  mrg     /* Warning about missing arg was already issued.  */
   4933  1.1  mrg     return const0_rtx;
   4934  1.1  mrg   else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
   4935  1.1  mrg     {
   4936  1.1  mrg       error ("invalid argument to %qD", fndecl);
   4937  1.1  mrg       return const0_rtx;
   4938  1.1  mrg     }
   4939  1.1  mrg   else
   4940  1.1  mrg     {
   4941  1.1  mrg       /* Number of frames to scan up the stack.  */
   4942  1.1  mrg       unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
   4943  1.1  mrg 
   4944  1.1  mrg       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
   4945  1.1  mrg 
   4946  1.1  mrg       /* Some ports cannot access arbitrary stack frames.  */
   4947  1.1  mrg       if (tem == NULL)
   4948  1.1  mrg 	{
   4949  1.1  mrg 	  warning (0, "unsupported argument to %qD", fndecl);
   4950  1.1  mrg 	  return const0_rtx;
   4951  1.1  mrg 	}
   4952  1.1  mrg 
   4953  1.1  mrg       if (count)
   4954  1.1  mrg 	{
   4955  1.1  mrg 	  /* Warn since no effort is made to ensure that any frame
   4956  1.1  mrg 	     beyond the current one exists or can be safely reached.  */
   4957  1.1  mrg 	  warning (OPT_Wframe_address, "calling %qD with "
   4958  1.1  mrg 		   "a nonzero argument is unsafe", fndecl);
   4959  1.1  mrg 	}
   4960  1.1  mrg 
   4961  1.1  mrg       /* For __builtin_frame_address, return what we've got.  */
   4962  1.1  mrg       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
   4963  1.1  mrg 	return tem;
   4964  1.1  mrg 
   4965  1.1  mrg       if (!REG_P (tem)
   4966  1.1  mrg 	  && ! CONSTANT_P (tem))
   4967  1.1  mrg 	tem = copy_addr_to_reg (tem);
   4968  1.1  mrg       return tem;
   4969  1.1  mrg     }
   4970  1.1  mrg }
   4971  1.1  mrg 
   4972  1.1  mrg /* Expand EXP, a call to the alloca builtin.  Return NULL_RTX if we
   4973  1.1  mrg    failed and the caller should emit a normal call.  */
   4974  1.1  mrg 
   4975  1.1  mrg static rtx
   4976  1.1  mrg expand_builtin_alloca (tree exp)
   4977  1.1  mrg {
   4978  1.1  mrg   rtx op0;
   4979  1.1  mrg   rtx result;
   4980  1.1  mrg   unsigned int align;
   4981  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   4982  1.1  mrg   HOST_WIDE_INT max_size;
   4983  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   4984  1.1  mrg   bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
   4985  1.1  mrg   bool valid_arglist
   4986  1.1  mrg     = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
   4987  1.1  mrg        ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
   4988  1.1  mrg 			   VOID_TYPE)
   4989  1.1  mrg        : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
   4990  1.1  mrg 	 ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
   4991  1.1  mrg 	 : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
   4992  1.1  mrg 
   4993  1.1  mrg   if (!valid_arglist)
   4994  1.1  mrg     return NULL_RTX;
   4995  1.1  mrg 
   4996  1.1  mrg   /* Compute the argument.  */
   4997  1.1  mrg   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
   4998  1.1  mrg 
   4999  1.1  mrg   /* Compute the alignment.  */
   5000  1.1  mrg   align = (fcode == BUILT_IN_ALLOCA
   5001  1.1  mrg 	   ? BIGGEST_ALIGNMENT
   5002  1.1  mrg 	   : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
   5003  1.1  mrg 
   5004  1.1  mrg   /* Compute the maximum size.  */
   5005  1.1  mrg   max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
   5006  1.1  mrg               ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
   5007  1.1  mrg               : -1);
   5008  1.1  mrg 
   5009  1.1  mrg   /* Allocate the desired space.  If the allocation stems from the declaration
   5010  1.1  mrg      of a variable-sized object, it cannot accumulate.  */
   5011  1.1  mrg   result
   5012  1.1  mrg     = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
   5013  1.1  mrg   result = convert_memory_address (ptr_mode, result);
   5014  1.1  mrg 
   5015  1.1  mrg   /* Dynamic allocations for variables are recorded during gimplification.  */
   5016  1.1  mrg   if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
   5017  1.1  mrg     record_dynamic_alloc (exp);
   5018  1.1  mrg 
   5019  1.1  mrg   return result;
   5020  1.1  mrg }
   5021  1.1  mrg 
   5022  1.1  mrg /* Emit a call to __asan_allocas_unpoison call in EXP.  Add to second argument
   5023  1.1  mrg    of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
   5024  1.1  mrg    STACK_DYNAMIC_OFFSET value.  See motivation for this in comment to
   5025  1.1  mrg    handle_builtin_stack_restore function.  */
   5026  1.1  mrg 
   5027  1.1  mrg static rtx
   5028  1.1  mrg expand_asan_emit_allocas_unpoison (tree exp)
   5029  1.1  mrg {
   5030  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   5031  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 1);
   5032  1.1  mrg   rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
   5033  1.1  mrg   rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
   5034  1.1  mrg   rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
   5035  1.1  mrg 				 stack_pointer_rtx, NULL_RTX, 0,
   5036  1.1  mrg 				 OPTAB_LIB_WIDEN);
   5037  1.1  mrg   off = convert_modes (ptr_mode, Pmode, off, 0);
   5038  1.1  mrg   bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
   5039  1.1  mrg 			     OPTAB_LIB_WIDEN);
   5040  1.1  mrg   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
   5041  1.1  mrg   ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
   5042  1.1  mrg 				 top, ptr_mode, bot, ptr_mode);
   5043  1.1  mrg   return ret;
   5044  1.1  mrg }
   5045  1.1  mrg 
   5046  1.1  mrg /* Expand a call to bswap builtin in EXP.
   5047  1.1  mrg    Return NULL_RTX if a normal call should be emitted rather than expanding the
   5048  1.1  mrg    function in-line.  If convenient, the result should be placed in TARGET.
   5049  1.1  mrg    SUBTARGET may be used as the target for computing one of EXP's operands.  */
   5050  1.1  mrg 
   5051  1.1  mrg static rtx
   5052  1.1  mrg expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
   5053  1.1  mrg 		      rtx subtarget)
   5054  1.1  mrg {
   5055  1.1  mrg   tree arg;
   5056  1.1  mrg   rtx op0;
   5057  1.1  mrg 
   5058  1.1  mrg   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
   5059  1.1  mrg     return NULL_RTX;
   5060  1.1  mrg 
   5061  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   5062  1.1  mrg   op0 = expand_expr (arg,
   5063  1.1  mrg 		     subtarget && GET_MODE (subtarget) == target_mode
   5064  1.1  mrg 		     ? subtarget : NULL_RTX,
   5065  1.1  mrg 		     target_mode, EXPAND_NORMAL);
   5066  1.1  mrg   if (GET_MODE (op0) != target_mode)
   5067  1.1  mrg     op0 = convert_to_mode (target_mode, op0, 1);
   5068  1.1  mrg 
   5069  1.1  mrg   target = expand_unop (target_mode, bswap_optab, op0, target, 1);
   5070  1.1  mrg 
   5071  1.1  mrg   gcc_assert (target);
   5072  1.1  mrg 
   5073  1.1  mrg   return convert_to_mode (target_mode, target, 1);
   5074  1.1  mrg }
   5075  1.1  mrg 
   5076  1.1  mrg /* Expand a call to a unary builtin in EXP.
   5077  1.1  mrg    Return NULL_RTX if a normal call should be emitted rather than expanding the
   5078  1.1  mrg    function in-line.  If convenient, the result should be placed in TARGET.
   5079  1.1  mrg    SUBTARGET may be used as the target for computing one of EXP's operands.  */
   5080  1.1  mrg 
   5081  1.1  mrg static rtx
   5082  1.1  mrg expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
   5083  1.1  mrg 		     rtx subtarget, optab op_optab)
   5084  1.1  mrg {
   5085  1.1  mrg   rtx op0;
   5086  1.1  mrg 
   5087  1.1  mrg   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
   5088  1.1  mrg     return NULL_RTX;
   5089  1.1  mrg 
   5090  1.1  mrg   /* Compute the argument.  */
   5091  1.1  mrg   op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
   5092  1.1  mrg 		     (subtarget
   5093  1.1  mrg 		      && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
   5094  1.1  mrg 			  == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
   5095  1.1  mrg 		     VOIDmode, EXPAND_NORMAL);
   5096  1.1  mrg   /* Compute op, into TARGET if possible.
   5097  1.1  mrg      Set TARGET to wherever the result comes back.  */
   5098  1.1  mrg   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
   5099  1.1  mrg 			op_optab, op0, target, op_optab != clrsb_optab);
   5100  1.1  mrg   gcc_assert (target);
   5101  1.1  mrg 
   5102  1.1  mrg   return convert_to_mode (target_mode, target, 0);
   5103  1.1  mrg }
   5104  1.1  mrg 
   5105  1.1  mrg /* Expand a call to __builtin_expect.  We just return our argument
   5106  1.1  mrg    as the builtin_expect semantic should've been already executed by
   5107  1.1  mrg    tree branch prediction pass. */
   5108  1.1  mrg 
   5109  1.1  mrg static rtx
   5110  1.1  mrg expand_builtin_expect (tree exp, rtx target)
   5111  1.1  mrg {
   5112  1.1  mrg   tree arg;
   5113  1.1  mrg 
   5114  1.1  mrg   if (call_expr_nargs (exp) < 2)
   5115  1.1  mrg     return const0_rtx;
   5116  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   5117  1.1  mrg 
   5118  1.1  mrg   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   5119  1.1  mrg   /* When guessing was done, the hints should be already stripped away.  */
   5120  1.1  mrg   gcc_assert (!flag_guess_branch_prob
   5121  1.1  mrg 	      || optimize == 0 || seen_error ());
   5122  1.1  mrg   return target;
   5123  1.1  mrg }
   5124  1.1  mrg 
   5125  1.1  mrg /* Expand a call to __builtin_expect_with_probability.  We just return our
   5126  1.1  mrg    argument as the builtin_expect semantic should've been already executed by
   5127  1.1  mrg    tree branch prediction pass.  */
   5128  1.1  mrg 
   5129  1.1  mrg static rtx
   5130  1.1  mrg expand_builtin_expect_with_probability (tree exp, rtx target)
   5131  1.1  mrg {
   5132  1.1  mrg   tree arg;
   5133  1.1  mrg 
   5134  1.1  mrg   if (call_expr_nargs (exp) < 3)
   5135  1.1  mrg     return const0_rtx;
   5136  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   5137  1.1  mrg 
   5138  1.1  mrg   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   5139  1.1  mrg   /* When guessing was done, the hints should be already stripped away.  */
   5140  1.1  mrg   gcc_assert (!flag_guess_branch_prob
   5141  1.1  mrg 	      || optimize == 0 || seen_error ());
   5142  1.1  mrg   return target;
   5143  1.1  mrg }
   5144  1.1  mrg 
   5145  1.1  mrg 
   5146  1.1  mrg /* Expand a call to __builtin_assume_aligned.  We just return our first
   5147  1.1  mrg    argument as the builtin_assume_aligned semantic should've been already
   5148  1.1  mrg    executed by CCP.  */
   5149  1.1  mrg 
   5150  1.1  mrg static rtx
   5151  1.1  mrg expand_builtin_assume_aligned (tree exp, rtx target)
   5152  1.1  mrg {
   5153  1.1  mrg   if (call_expr_nargs (exp) < 2)
   5154  1.1  mrg     return const0_rtx;
   5155  1.1  mrg   target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
   5156  1.1  mrg 			EXPAND_NORMAL);
   5157  1.1  mrg   gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
   5158  1.1  mrg 	      && (call_expr_nargs (exp) < 3
   5159  1.1  mrg 		  || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
   5160  1.1  mrg   return target;
   5161  1.1  mrg }
   5162  1.1  mrg 
   5163  1.1  mrg void
   5164  1.1  mrg expand_builtin_trap (void)
   5165  1.1  mrg {
   5166  1.1  mrg   if (targetm.have_trap ())
   5167  1.1  mrg     {
   5168  1.1  mrg       rtx_insn *insn = emit_insn (targetm.gen_trap ());
   5169  1.1  mrg       /* For trap insns when not accumulating outgoing args force
   5170  1.1  mrg 	 REG_ARGS_SIZE note to prevent crossjumping of calls with
   5171  1.1  mrg 	 different args sizes.  */
   5172  1.1  mrg       if (!ACCUMULATE_OUTGOING_ARGS)
   5173  1.1  mrg 	add_args_size_note (insn, stack_pointer_delta);
   5174  1.1  mrg     }
   5175  1.1  mrg   else
   5176  1.1  mrg     {
   5177  1.1  mrg       tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
   5178  1.1  mrg       tree call_expr = build_call_expr (fn, 0);
   5179  1.1  mrg       expand_call (call_expr, NULL_RTX, false);
   5180  1.1  mrg     }
   5181  1.1  mrg 
   5182  1.1  mrg   emit_barrier ();
   5183  1.1  mrg }
   5184  1.1  mrg 
   5185  1.1  mrg /* Expand a call to __builtin_unreachable.  We do nothing except emit
   5186  1.1  mrg    a barrier saying that control flow will not pass here.
   5187  1.1  mrg 
   5188  1.1  mrg    It is the responsibility of the program being compiled to ensure
   5189  1.1  mrg    that control flow does never reach __builtin_unreachable.  */
   5190  1.1  mrg static void
   5191  1.1  mrg expand_builtin_unreachable (void)
   5192  1.1  mrg {
   5193  1.1  mrg   emit_barrier ();
   5194  1.1  mrg }
   5195  1.1  mrg 
   5196  1.1  mrg /* Expand EXP, a call to fabs, fabsf or fabsl.
   5197  1.1  mrg    Return NULL_RTX if a normal call should be emitted rather than expanding
   5198  1.1  mrg    the function inline.  If convenient, the result should be placed
   5199  1.1  mrg    in TARGET.  SUBTARGET may be used as the target for computing
   5200  1.1  mrg    the operand.  */
   5201  1.1  mrg 
   5202  1.1  mrg static rtx
   5203  1.1  mrg expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
   5204  1.1  mrg {
   5205  1.1  mrg   machine_mode mode;
   5206  1.1  mrg   tree arg;
   5207  1.1  mrg   rtx op0;
   5208  1.1  mrg 
   5209  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   5210  1.1  mrg     return NULL_RTX;
   5211  1.1  mrg 
   5212  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   5213  1.1  mrg   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
   5214  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (arg));
   5215  1.1  mrg   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
   5216  1.1  mrg   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
   5217  1.1  mrg }
   5218  1.1  mrg 
   5219  1.1  mrg /* Expand EXP, a call to copysign, copysignf, or copysignl.
   5220  1.1  mrg    Return NULL is a normal call should be emitted rather than expanding the
   5221  1.1  mrg    function inline.  If convenient, the result should be placed in TARGET.
   5222  1.1  mrg    SUBTARGET may be used as the target for computing the operand.  */
   5223  1.1  mrg 
   5224  1.1  mrg static rtx
   5225  1.1  mrg expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
   5226  1.1  mrg {
   5227  1.1  mrg   rtx op0, op1;
   5228  1.1  mrg   tree arg;
   5229  1.1  mrg 
   5230  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
   5231  1.1  mrg     return NULL_RTX;
   5232  1.1  mrg 
   5233  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   5234  1.1  mrg   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
   5235  1.1  mrg 
   5236  1.1  mrg   arg = CALL_EXPR_ARG (exp, 1);
   5237  1.1  mrg   op1 = expand_normal (arg);
   5238  1.1  mrg 
   5239  1.1  mrg   return expand_copysign (op0, op1, target);
   5240  1.1  mrg }
   5241  1.1  mrg 
   5242  1.1  mrg /* Emit a call to __builtin___clear_cache.  */
   5243  1.1  mrg 
   5244  1.1  mrg void
   5245  1.1  mrg default_emit_call_builtin___clear_cache (rtx begin, rtx end)
   5246  1.1  mrg {
   5247  1.1  mrg   rtx callee = gen_rtx_SYMBOL_REF (Pmode,
   5248  1.1  mrg 				   BUILTIN_ASM_NAME_PTR
   5249  1.1  mrg 				   (BUILT_IN_CLEAR_CACHE));
   5250  1.1  mrg 
   5251  1.1  mrg   emit_library_call (callee,
   5252  1.1  mrg 		     LCT_NORMAL, VOIDmode,
   5253  1.1  mrg 		     convert_memory_address (ptr_mode, begin), ptr_mode,
   5254  1.1  mrg 		     convert_memory_address (ptr_mode, end), ptr_mode);
   5255  1.1  mrg }
   5256  1.1  mrg 
   5257  1.1  mrg /* Emit a call to __builtin___clear_cache, unless the target specifies
   5258  1.1  mrg    it as do-nothing.  This function can be used by trampoline
   5259  1.1  mrg    finalizers to duplicate the effects of expanding a call to the
   5260  1.1  mrg    clear_cache builtin.  */
   5261  1.1  mrg 
   5262  1.1  mrg void
   5263  1.1  mrg maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
   5264  1.1  mrg {
   5265  1.1  mrg   gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
   5266  1.1  mrg 	       || CONST_INT_P (begin))
   5267  1.1  mrg 	      && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
   5268  1.1  mrg 		  || CONST_INT_P (end)));
   5269  1.1  mrg 
   5270  1.1  mrg   if (targetm.have_clear_cache ())
   5271  1.1  mrg     {
   5272  1.1  mrg       /* We have a "clear_cache" insn, and it will handle everything.  */
   5273  1.1  mrg       class expand_operand ops[2];
   5274  1.1  mrg 
   5275  1.1  mrg       create_address_operand (&ops[0], begin);
   5276  1.1  mrg       create_address_operand (&ops[1], end);
   5277  1.1  mrg 
   5278  1.1  mrg       if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
   5279  1.1  mrg 	return;
   5280  1.1  mrg     }
   5281  1.1  mrg   else
   5282  1.1  mrg     {
   5283  1.1  mrg #ifndef CLEAR_INSN_CACHE
   5284  1.1  mrg       /* There is no "clear_cache" insn, and __clear_cache() in libgcc
   5285  1.1  mrg 	 does nothing.  There is no need to call it.  Do nothing.  */
   5286  1.1  mrg       return;
   5287  1.1  mrg #endif /* CLEAR_INSN_CACHE */
   5288  1.1  mrg     }
   5289  1.1  mrg 
   5290  1.1  mrg   targetm.calls.emit_call_builtin___clear_cache (begin, end);
   5291  1.1  mrg }
   5292  1.1  mrg 
   5293  1.1  mrg /* Expand a call to __builtin___clear_cache.  */
   5294  1.1  mrg 
   5295  1.1  mrg static void
   5296  1.1  mrg expand_builtin___clear_cache (tree exp)
   5297  1.1  mrg {
   5298  1.1  mrg   tree begin, end;
   5299  1.1  mrg   rtx begin_rtx, end_rtx;
   5300  1.1  mrg 
   5301  1.1  mrg   /* We must not expand to a library call.  If we did, any
   5302  1.1  mrg      fallback library function in libgcc that might contain a call to
   5303  1.1  mrg      __builtin___clear_cache() would recurse infinitely.  */
   5304  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   5305  1.1  mrg     {
   5306  1.1  mrg       error ("both arguments to %<__builtin___clear_cache%> must be pointers");
   5307  1.1  mrg       return;
   5308  1.1  mrg     }
   5309  1.1  mrg 
   5310  1.1  mrg   begin = CALL_EXPR_ARG (exp, 0);
   5311  1.1  mrg   begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
   5312  1.1  mrg 
   5313  1.1  mrg   end = CALL_EXPR_ARG (exp, 1);
   5314  1.1  mrg   end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
   5315  1.1  mrg 
   5316  1.1  mrg   maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
   5317  1.1  mrg }
   5318  1.1  mrg 
   5319  1.1  mrg /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
   5320  1.1  mrg 
   5321  1.1  mrg static rtx
   5322  1.1  mrg round_trampoline_addr (rtx tramp)
   5323  1.1  mrg {
   5324  1.1  mrg   rtx temp, addend, mask;
   5325  1.1  mrg 
   5326  1.1  mrg   /* If we don't need too much alignment, we'll have been guaranteed
   5327  1.1  mrg      proper alignment by get_trampoline_type.  */
   5328  1.1  mrg   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
   5329  1.1  mrg     return tramp;
   5330  1.1  mrg 
   5331  1.1  mrg   /* Round address up to desired boundary.  */
   5332  1.1  mrg   temp = gen_reg_rtx (Pmode);
   5333  1.1  mrg   addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
   5334  1.1  mrg   mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
   5335  1.1  mrg 
   5336  1.1  mrg   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
   5337  1.1  mrg 			       temp, 0, OPTAB_LIB_WIDEN);
   5338  1.1  mrg   tramp = expand_simple_binop (Pmode, AND, temp, mask,
   5339  1.1  mrg 			       temp, 0, OPTAB_LIB_WIDEN);
   5340  1.1  mrg 
   5341  1.1  mrg   return tramp;
   5342  1.1  mrg }
   5343  1.1  mrg 
   5344  1.1  mrg static rtx
   5345  1.1  mrg expand_builtin_init_trampoline (tree exp, bool onstack)
   5346  1.1  mrg {
   5347  1.1  mrg   tree t_tramp, t_func, t_chain;
   5348  1.1  mrg   rtx m_tramp, r_tramp, r_chain, tmp;
   5349  1.1  mrg 
   5350  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
   5351  1.1  mrg 			 POINTER_TYPE, VOID_TYPE))
   5352  1.1  mrg     return NULL_RTX;
   5353  1.1  mrg 
   5354  1.1  mrg   t_tramp = CALL_EXPR_ARG (exp, 0);
   5355  1.1  mrg   t_func = CALL_EXPR_ARG (exp, 1);
   5356  1.1  mrg   t_chain = CALL_EXPR_ARG (exp, 2);
   5357  1.1  mrg 
   5358  1.1  mrg   r_tramp = expand_normal (t_tramp);
   5359  1.1  mrg   m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
   5360  1.1  mrg   MEM_NOTRAP_P (m_tramp) = 1;
   5361  1.1  mrg 
   5362  1.1  mrg   /* If ONSTACK, the TRAMP argument should be the address of a field
   5363  1.1  mrg      within the local function's FRAME decl.  Either way, let's see if
   5364  1.1  mrg      we can fill in the MEM_ATTRs for this memory.  */
   5365  1.1  mrg   if (TREE_CODE (t_tramp) == ADDR_EXPR)
   5366  1.1  mrg     set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
   5367  1.1  mrg 
   5368  1.1  mrg   /* Creator of a heap trampoline is responsible for making sure the
   5369  1.1  mrg      address is aligned to at least STACK_BOUNDARY.  Normally malloc
   5370  1.1  mrg      will ensure this anyhow.  */
   5371  1.1  mrg   tmp = round_trampoline_addr (r_tramp);
   5372  1.1  mrg   if (tmp != r_tramp)
   5373  1.1  mrg     {
   5374  1.1  mrg       m_tramp = change_address (m_tramp, BLKmode, tmp);
   5375  1.1  mrg       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
   5376  1.1  mrg       set_mem_size (m_tramp, TRAMPOLINE_SIZE);
   5377  1.1  mrg     }
   5378  1.1  mrg 
   5379  1.1  mrg   /* The FUNC argument should be the address of the nested function.
   5380  1.1  mrg      Extract the actual function decl to pass to the hook.  */
   5381  1.1  mrg   gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
   5382  1.1  mrg   t_func = TREE_OPERAND (t_func, 0);
   5383  1.1  mrg   gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
   5384  1.1  mrg 
   5385  1.1  mrg   r_chain = expand_normal (t_chain);
   5386  1.1  mrg 
   5387  1.1  mrg   /* Generate insns to initialize the trampoline.  */
   5388  1.1  mrg   targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
   5389  1.1  mrg 
   5390  1.1  mrg   if (onstack)
   5391  1.1  mrg     {
   5392  1.1  mrg       trampolines_created = 1;
   5393  1.1  mrg 
   5394  1.1  mrg       if (targetm.calls.custom_function_descriptors != 0)
   5395  1.1  mrg 	warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
   5396  1.1  mrg 		    "trampoline generated for nested function %qD", t_func);
   5397  1.1  mrg     }
   5398  1.1  mrg 
   5399  1.1  mrg   return const0_rtx;
   5400  1.1  mrg }
   5401  1.1  mrg 
   5402  1.1  mrg static rtx
   5403  1.1  mrg expand_builtin_adjust_trampoline (tree exp)
   5404  1.1  mrg {
   5405  1.1  mrg   rtx tramp;
   5406  1.1  mrg 
   5407  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   5408  1.1  mrg     return NULL_RTX;
   5409  1.1  mrg 
   5410  1.1  mrg   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
   5411  1.1  mrg   tramp = round_trampoline_addr (tramp);
   5412  1.1  mrg   if (targetm.calls.trampoline_adjust_address)
   5413  1.1  mrg     tramp = targetm.calls.trampoline_adjust_address (tramp);
   5414  1.1  mrg 
   5415  1.1  mrg   return tramp;
   5416  1.1  mrg }
   5417  1.1  mrg 
   5418  1.1  mrg /* Expand a call to the builtin descriptor initialization routine.
   5419  1.1  mrg    A descriptor is made up of a couple of pointers to the static
   5420  1.1  mrg    chain and the code entry in this order.  */
   5421  1.1  mrg 
   5422  1.1  mrg static rtx
   5423  1.1  mrg expand_builtin_init_descriptor (tree exp)
   5424  1.1  mrg {
   5425  1.1  mrg   tree t_descr, t_func, t_chain;
   5426  1.1  mrg   rtx m_descr, r_descr, r_func, r_chain;
   5427  1.1  mrg 
   5428  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
   5429  1.1  mrg 			 VOID_TYPE))
   5430  1.1  mrg     return NULL_RTX;
   5431  1.1  mrg 
   5432  1.1  mrg   t_descr = CALL_EXPR_ARG (exp, 0);
   5433  1.1  mrg   t_func = CALL_EXPR_ARG (exp, 1);
   5434  1.1  mrg   t_chain = CALL_EXPR_ARG (exp, 2);
   5435  1.1  mrg 
   5436  1.1  mrg   r_descr = expand_normal (t_descr);
   5437  1.1  mrg   m_descr = gen_rtx_MEM (BLKmode, r_descr);
   5438  1.1  mrg   MEM_NOTRAP_P (m_descr) = 1;
   5439  1.1  mrg   set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
   5440  1.1  mrg 
   5441  1.1  mrg   r_func = expand_normal (t_func);
   5442  1.1  mrg   r_chain = expand_normal (t_chain);
   5443  1.1  mrg 
   5444  1.1  mrg   /* Generate insns to initialize the descriptor.  */
   5445  1.1  mrg   emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
   5446  1.1  mrg   emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
   5447  1.1  mrg 				     POINTER_SIZE / BITS_PER_UNIT), r_func);
   5448  1.1  mrg 
   5449  1.1  mrg   return const0_rtx;
   5450  1.1  mrg }
   5451  1.1  mrg 
   5452  1.1  mrg /* Expand a call to the builtin descriptor adjustment routine.  */
   5453  1.1  mrg 
   5454  1.1  mrg static rtx
   5455  1.1  mrg expand_builtin_adjust_descriptor (tree exp)
   5456  1.1  mrg {
   5457  1.1  mrg   rtx tramp;
   5458  1.1  mrg 
   5459  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   5460  1.1  mrg     return NULL_RTX;
   5461  1.1  mrg 
   5462  1.1  mrg   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
   5463  1.1  mrg 
   5464  1.1  mrg   /* Unalign the descriptor to allow runtime identification.  */
   5465  1.1  mrg   tramp = plus_constant (ptr_mode, tramp,
   5466  1.1  mrg 			 targetm.calls.custom_function_descriptors);
   5467  1.1  mrg 
   5468  1.1  mrg   return force_operand (tramp, NULL_RTX);
   5469  1.1  mrg }
   5470  1.1  mrg 
   5471  1.1  mrg /* Expand the call EXP to the built-in signbit, signbitf or signbitl
   5472  1.1  mrg    function.  The function first checks whether the back end provides
   5473  1.1  mrg    an insn to implement signbit for the respective mode.  If not, it
   5474  1.1  mrg    checks whether the floating point format of the value is such that
   5475  1.1  mrg    the sign bit can be extracted.  If that is not the case, error out.
   5476  1.1  mrg    EXP is the expression that is a call to the builtin function; if
   5477  1.1  mrg    convenient, the result should be placed in TARGET.  */
   5478  1.1  mrg static rtx
   5479  1.1  mrg expand_builtin_signbit (tree exp, rtx target)
   5480  1.1  mrg {
   5481  1.1  mrg   const struct real_format *fmt;
   5482  1.1  mrg   scalar_float_mode fmode;
   5483  1.1  mrg   scalar_int_mode rmode, imode;
   5484  1.1  mrg   tree arg;
   5485  1.1  mrg   int word, bitpos;
   5486  1.1  mrg   enum insn_code icode;
   5487  1.1  mrg   rtx temp;
   5488  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   5489  1.1  mrg 
   5490  1.1  mrg   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
   5491  1.1  mrg     return NULL_RTX;
   5492  1.1  mrg 
   5493  1.1  mrg   arg = CALL_EXPR_ARG (exp, 0);
   5494  1.1  mrg   fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
   5495  1.1  mrg   rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
   5496  1.1  mrg   fmt = REAL_MODE_FORMAT (fmode);
   5497  1.1  mrg 
   5498  1.1  mrg   arg = builtin_save_expr (arg);
   5499  1.1  mrg 
   5500  1.1  mrg   /* Expand the argument yielding a RTX expression. */
   5501  1.1  mrg   temp = expand_normal (arg);
   5502  1.1  mrg 
   5503  1.1  mrg   /* Check if the back end provides an insn that handles signbit for the
   5504  1.1  mrg      argument's mode. */
   5505  1.1  mrg   icode = optab_handler (signbit_optab, fmode);
   5506  1.1  mrg   if (icode != CODE_FOR_nothing)
   5507  1.1  mrg     {
   5508  1.1  mrg       rtx_insn *last = get_last_insn ();
   5509  1.1  mrg       target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
   5510  1.1  mrg       if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
   5511  1.1  mrg 	return target;
   5512  1.1  mrg       delete_insns_since (last);
   5513  1.1  mrg     }
   5514  1.1  mrg 
   5515  1.1  mrg   /* For floating point formats without a sign bit, implement signbit
   5516  1.1  mrg      as "ARG < 0.0".  */
   5517  1.1  mrg   bitpos = fmt->signbit_ro;
   5518  1.1  mrg   if (bitpos < 0)
   5519  1.1  mrg   {
   5520  1.1  mrg     /* But we can't do this if the format supports signed zero.  */
   5521  1.1  mrg     gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
   5522  1.1  mrg 
   5523  1.1  mrg     arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
   5524  1.1  mrg 		       build_real (TREE_TYPE (arg), dconst0));
   5525  1.1  mrg     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   5526  1.1  mrg   }
   5527  1.1  mrg 
   5528  1.1  mrg   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
   5529  1.1  mrg     {
   5530  1.1  mrg       imode = int_mode_for_mode (fmode).require ();
   5531  1.1  mrg       temp = gen_lowpart (imode, temp);
   5532  1.1  mrg     }
   5533  1.1  mrg   else
   5534  1.1  mrg     {
   5535  1.1  mrg       imode = word_mode;
   5536  1.1  mrg       /* Handle targets with different FP word orders.  */
   5537  1.1  mrg       if (FLOAT_WORDS_BIG_ENDIAN)
   5538  1.1  mrg 	word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
   5539  1.1  mrg       else
   5540  1.1  mrg 	word = bitpos / BITS_PER_WORD;
   5541  1.1  mrg       temp = operand_subword_force (temp, word, fmode);
   5542  1.1  mrg       bitpos = bitpos % BITS_PER_WORD;
   5543  1.1  mrg     }
   5544  1.1  mrg 
   5545  1.1  mrg   /* Force the intermediate word_mode (or narrower) result into a
   5546  1.1  mrg      register.  This avoids attempting to create paradoxical SUBREGs
   5547  1.1  mrg      of floating point modes below.  */
   5548  1.1  mrg   temp = force_reg (imode, temp);
   5549  1.1  mrg 
   5550  1.1  mrg   /* If the bitpos is within the "result mode" lowpart, the operation
   5551  1.1  mrg      can be implement with a single bitwise AND.  Otherwise, we need
   5552  1.1  mrg      a right shift and an AND.  */
   5553  1.1  mrg 
   5554  1.1  mrg   if (bitpos < GET_MODE_BITSIZE (rmode))
   5555  1.1  mrg     {
   5556  1.1  mrg       wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
   5557  1.1  mrg 
   5558  1.1  mrg       if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
   5559  1.1  mrg 	temp = gen_lowpart (rmode, temp);
   5560  1.1  mrg       temp = expand_binop (rmode, and_optab, temp,
   5561  1.1  mrg 			   immed_wide_int_const (mask, rmode),
   5562  1.1  mrg 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
   5563  1.1  mrg     }
   5564  1.1  mrg   else
   5565  1.1  mrg     {
   5566  1.1  mrg       /* Perform a logical right shift to place the signbit in the least
   5567  1.1  mrg 	 significant bit, then truncate the result to the desired mode
   5568  1.1  mrg 	 and mask just this bit.  */
   5569  1.1  mrg       temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
   5570  1.1  mrg       temp = gen_lowpart (rmode, temp);
   5571  1.1  mrg       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
   5572  1.1  mrg 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
   5573  1.1  mrg     }
   5574  1.1  mrg 
   5575  1.1  mrg   return temp;
   5576  1.1  mrg }
   5577  1.1  mrg 
   5578  1.1  mrg /* Expand fork or exec calls.  TARGET is the desired target of the
   5579  1.1  mrg    call.  EXP is the call. FN is the
   5580  1.1  mrg    identificator of the actual function.  IGNORE is nonzero if the
   5581  1.1  mrg    value is to be ignored.  */
   5582  1.1  mrg 
   5583  1.1  mrg static rtx
   5584  1.1  mrg expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
   5585  1.1  mrg {
   5586  1.1  mrg   tree id, decl;
   5587  1.1  mrg   tree call;
   5588  1.1  mrg 
   5589  1.1  mrg   /* If we are not profiling, just call the function.  */
   5590  1.1  mrg   if (!profile_arc_flag)
   5591  1.1  mrg     return NULL_RTX;
   5592  1.1  mrg 
   5593  1.1  mrg   /* Otherwise call the wrapper.  This should be equivalent for the rest of
   5594  1.1  mrg      compiler, so the code does not diverge, and the wrapper may run the
   5595  1.1  mrg      code necessary for keeping the profiling sane.  */
   5596  1.1  mrg 
   5597  1.1  mrg   switch (DECL_FUNCTION_CODE (fn))
   5598  1.1  mrg     {
   5599  1.1  mrg     case BUILT_IN_FORK:
   5600  1.1  mrg       id = get_identifier ("__gcov_fork");
   5601  1.1  mrg       break;
   5602  1.1  mrg 
   5603  1.1  mrg     case BUILT_IN_EXECL:
   5604  1.1  mrg       id = get_identifier ("__gcov_execl");
   5605  1.1  mrg       break;
   5606  1.1  mrg 
   5607  1.1  mrg     case BUILT_IN_EXECV:
   5608  1.1  mrg       id = get_identifier ("__gcov_execv");
   5609  1.1  mrg       break;
   5610  1.1  mrg 
   5611  1.1  mrg     case BUILT_IN_EXECLP:
   5612  1.1  mrg       id = get_identifier ("__gcov_execlp");
   5613  1.1  mrg       break;
   5614  1.1  mrg 
   5615  1.1  mrg     case BUILT_IN_EXECLE:
   5616  1.1  mrg       id = get_identifier ("__gcov_execle");
   5617  1.1  mrg       break;
   5618  1.1  mrg 
   5619  1.1  mrg     case BUILT_IN_EXECVP:
   5620  1.1  mrg       id = get_identifier ("__gcov_execvp");
   5621  1.1  mrg       break;
   5622  1.1  mrg 
   5623  1.1  mrg     case BUILT_IN_EXECVE:
   5624  1.1  mrg       id = get_identifier ("__gcov_execve");
   5625  1.1  mrg       break;
   5626  1.1  mrg 
   5627  1.1  mrg     default:
   5628  1.1  mrg       gcc_unreachable ();
   5629  1.1  mrg     }
   5630  1.1  mrg 
   5631  1.1  mrg   decl = build_decl (DECL_SOURCE_LOCATION (fn),
   5632  1.1  mrg 		     FUNCTION_DECL, id, TREE_TYPE (fn));
   5633  1.1  mrg   DECL_EXTERNAL (decl) = 1;
   5634  1.1  mrg   TREE_PUBLIC (decl) = 1;
   5635  1.1  mrg   DECL_ARTIFICIAL (decl) = 1;
   5636  1.1  mrg   TREE_NOTHROW (decl) = 1;
   5637  1.1  mrg   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
   5638  1.1  mrg   DECL_VISIBILITY_SPECIFIED (decl) = 1;
   5639  1.1  mrg   call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
   5640  1.1  mrg   return expand_call (call, target, ignore);
   5641  1.1  mrg  }
   5642  1.1  mrg 
   5643  1.1  mrg 
   5644  1.1  mrg 
   5645  1.1  mrg /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
   5647  1.1  mrg    the pointer in these functions is void*, the tree optimizers may remove
   5648  1.1  mrg    casts.  The mode computed in expand_builtin isn't reliable either, due
   5649  1.1  mrg    to __sync_bool_compare_and_swap.
   5650  1.1  mrg 
   5651  1.1  mrg    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
   5652  1.1  mrg    group of builtins.  This gives us log2 of the mode size.  */
   5653  1.1  mrg 
   5654  1.1  mrg static inline machine_mode
   5655  1.1  mrg get_builtin_sync_mode (int fcode_diff)
   5656  1.1  mrg {
   5657  1.1  mrg   /* The size is not negotiable, so ask not to get BLKmode in return
   5658  1.1  mrg      if the target indicates that a smaller size would be better.  */
   5659  1.1  mrg   return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
   5660  1.1  mrg }
   5661  1.1  mrg 
   5662  1.1  mrg /* Expand the memory expression LOC and return the appropriate memory operand
   5663  1.1  mrg    for the builtin_sync operations.  */
   5664  1.1  mrg 
   5665  1.1  mrg static rtx
   5666  1.1  mrg get_builtin_sync_mem (tree loc, machine_mode mode)
   5667  1.1  mrg {
   5668  1.1  mrg   rtx addr, mem;
   5669  1.1  mrg   int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
   5670  1.1  mrg 				    ? TREE_TYPE (TREE_TYPE (loc))
   5671  1.1  mrg 				    : TREE_TYPE (loc));
   5672  1.1  mrg   scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
   5673  1.1  mrg 
   5674  1.1  mrg   addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
   5675  1.1  mrg   addr = convert_memory_address (addr_mode, addr);
   5676  1.1  mrg 
   5677  1.1  mrg   /* Note that we explicitly do not want any alias information for this
   5678  1.1  mrg      memory, so that we kill all other live memories.  Otherwise we don't
   5679  1.1  mrg      satisfy the full barrier semantics of the intrinsic.  */
   5680  1.1  mrg   mem = gen_rtx_MEM (mode, addr);
   5681  1.1  mrg 
   5682  1.1  mrg   set_mem_addr_space (mem, addr_space);
   5683  1.1  mrg 
   5684  1.1  mrg   mem = validize_mem (mem);
   5685  1.1  mrg 
   5686  1.1  mrg   /* The alignment needs to be at least according to that of the mode.  */
   5687  1.1  mrg   set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
   5688  1.1  mrg 			   get_pointer_alignment (loc)));
   5689  1.1  mrg   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
   5690  1.1  mrg   MEM_VOLATILE_P (mem) = 1;
   5691  1.1  mrg 
   5692  1.1  mrg   return mem;
   5693  1.1  mrg }
   5694  1.1  mrg 
   5695  1.1  mrg /* Make sure an argument is in the right mode.
   5696  1.1  mrg    EXP is the tree argument.
   5697  1.1  mrg    MODE is the mode it should be in.  */
   5698  1.1  mrg 
   5699  1.1  mrg static rtx
   5700  1.1  mrg expand_expr_force_mode (tree exp, machine_mode mode)
   5701  1.1  mrg {
   5702  1.1  mrg   rtx val;
   5703  1.1  mrg   machine_mode old_mode;
   5704  1.1  mrg 
   5705  1.1  mrg   if (TREE_CODE (exp) == SSA_NAME
   5706  1.1  mrg       && TYPE_MODE (TREE_TYPE (exp)) != mode)
   5707  1.1  mrg     {
   5708  1.1  mrg       /* Undo argument promotion if possible, as combine might not
   5709  1.1  mrg 	 be able to do it later due to MEM_VOLATILE_P uses in the
   5710  1.1  mrg 	 patterns.  */
   5711  1.1  mrg       gimple *g = get_gimple_for_ssa_name (exp);
   5712  1.1  mrg       if (g && gimple_assign_cast_p (g))
   5713  1.1  mrg 	{
   5714  1.1  mrg 	  tree rhs = gimple_assign_rhs1 (g);
   5715  1.1  mrg 	  tree_code code = gimple_assign_rhs_code (g);
   5716  1.1  mrg 	  if (CONVERT_EXPR_CODE_P (code)
   5717  1.1  mrg 	      && TYPE_MODE (TREE_TYPE (rhs)) == mode
   5718  1.1  mrg 	      && INTEGRAL_TYPE_P (TREE_TYPE (exp))
   5719  1.1  mrg 	      && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
   5720  1.1  mrg 	      && (TYPE_PRECISION (TREE_TYPE (exp))
   5721  1.1  mrg 		  > TYPE_PRECISION (TREE_TYPE (rhs))))
   5722  1.1  mrg 	    exp = rhs;
   5723  1.1  mrg 	}
   5724  1.1  mrg     }
   5725  1.1  mrg 
   5726  1.1  mrg   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
   5727  1.1  mrg   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
   5728  1.1  mrg      of CONST_INTs, where we know the old_mode only from the call argument.  */
   5729  1.1  mrg 
   5730  1.1  mrg   old_mode = GET_MODE (val);
   5731  1.1  mrg   if (old_mode == VOIDmode)
   5732  1.1  mrg     old_mode = TYPE_MODE (TREE_TYPE (exp));
   5733  1.1  mrg   val = convert_modes (mode, old_mode, val, 1);
   5734  1.1  mrg   return val;
   5735  1.1  mrg }
   5736  1.1  mrg 
   5737  1.1  mrg 
   5738  1.1  mrg /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
   5739  1.1  mrg    EXP is the CALL_EXPR.  CODE is the rtx code
   5740  1.1  mrg    that corresponds to the arithmetic or logical operation from the name;
   5741  1.1  mrg    an exception here is that NOT actually means NAND.  TARGET is an optional
   5742  1.1  mrg    place for us to store the results; AFTER is true if this is the
   5743  1.1  mrg    fetch_and_xxx form.  */
   5744  1.1  mrg 
   5745  1.1  mrg static rtx
   5746  1.1  mrg expand_builtin_sync_operation (machine_mode mode, tree exp,
   5747  1.1  mrg 			       enum rtx_code code, bool after,
   5748  1.1  mrg 			       rtx target)
   5749  1.1  mrg {
   5750  1.1  mrg   rtx val, mem;
   5751  1.1  mrg   location_t loc = EXPR_LOCATION (exp);
   5752  1.1  mrg 
   5753  1.1  mrg   if (code == NOT && warn_sync_nand)
   5754  1.1  mrg     {
   5755  1.1  mrg       tree fndecl = get_callee_fndecl (exp);
   5756  1.1  mrg       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   5757  1.1  mrg 
   5758  1.1  mrg       static bool warned_f_a_n, warned_n_a_f;
   5759  1.1  mrg 
   5760  1.1  mrg       switch (fcode)
   5761  1.1  mrg 	{
   5762  1.1  mrg 	case BUILT_IN_SYNC_FETCH_AND_NAND_1:
   5763  1.1  mrg 	case BUILT_IN_SYNC_FETCH_AND_NAND_2:
   5764  1.1  mrg 	case BUILT_IN_SYNC_FETCH_AND_NAND_4:
   5765  1.1  mrg 	case BUILT_IN_SYNC_FETCH_AND_NAND_8:
   5766  1.1  mrg 	case BUILT_IN_SYNC_FETCH_AND_NAND_16:
   5767  1.1  mrg 	  if (warned_f_a_n)
   5768  1.1  mrg 	    break;
   5769  1.1  mrg 
   5770  1.1  mrg 	  fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
   5771  1.1  mrg 	  inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
   5772  1.1  mrg 	  warned_f_a_n = true;
   5773  1.1  mrg 	  break;
   5774  1.1  mrg 
   5775  1.1  mrg 	case BUILT_IN_SYNC_NAND_AND_FETCH_1:
   5776  1.1  mrg 	case BUILT_IN_SYNC_NAND_AND_FETCH_2:
   5777  1.1  mrg 	case BUILT_IN_SYNC_NAND_AND_FETCH_4:
   5778  1.1  mrg 	case BUILT_IN_SYNC_NAND_AND_FETCH_8:
   5779  1.1  mrg 	case BUILT_IN_SYNC_NAND_AND_FETCH_16:
   5780  1.1  mrg 	  if (warned_n_a_f)
   5781  1.1  mrg 	    break;
   5782  1.1  mrg 
   5783  1.1  mrg 	 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
   5784  1.1  mrg 	  inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
   5785  1.1  mrg 	  warned_n_a_f = true;
   5786  1.1  mrg 	  break;
   5787  1.1  mrg 
   5788  1.1  mrg 	default:
   5789  1.1  mrg 	  gcc_unreachable ();
   5790  1.1  mrg 	}
   5791  1.1  mrg     }
   5792  1.1  mrg 
   5793  1.1  mrg   /* Expand the operands.  */
   5794  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   5795  1.1  mrg   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
   5796  1.1  mrg 
   5797  1.1  mrg   return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
   5798  1.1  mrg 				 after);
   5799  1.1  mrg }
   5800  1.1  mrg 
   5801  1.1  mrg /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
   5802  1.1  mrg    intrinsics. EXP is the CALL_EXPR.  IS_BOOL is
   5803  1.1  mrg    true if this is the boolean form.  TARGET is a place for us to store the
   5804  1.1  mrg    results; this is NOT optional if IS_BOOL is true.  */
   5805  1.1  mrg 
   5806  1.1  mrg static rtx
   5807  1.1  mrg expand_builtin_compare_and_swap (machine_mode mode, tree exp,
   5808  1.1  mrg 				 bool is_bool, rtx target)
   5809  1.1  mrg {
   5810  1.1  mrg   rtx old_val, new_val, mem;
   5811  1.1  mrg   rtx *pbool, *poval;
   5812  1.1  mrg 
   5813  1.1  mrg   /* Expand the operands.  */
   5814  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   5815  1.1  mrg   old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
   5816  1.1  mrg   new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
   5817  1.1  mrg 
   5818  1.1  mrg   pbool = poval = NULL;
   5819  1.1  mrg   if (target != const0_rtx)
   5820  1.1  mrg     {
   5821  1.1  mrg       if (is_bool)
   5822  1.1  mrg 	pbool = &target;
   5823  1.1  mrg       else
   5824  1.1  mrg 	poval = &target;
   5825  1.1  mrg     }
   5826  1.1  mrg   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
   5827  1.1  mrg 				       false, MEMMODEL_SYNC_SEQ_CST,
   5828  1.1  mrg 				       MEMMODEL_SYNC_SEQ_CST))
   5829  1.1  mrg     return NULL_RTX;
   5830  1.1  mrg 
   5831  1.1  mrg   return target;
   5832  1.1  mrg }
   5833  1.1  mrg 
   5834  1.1  mrg /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
   5835  1.1  mrg    general form is actually an atomic exchange, and some targets only
   5836  1.1  mrg    support a reduced form with the second argument being a constant 1.
   5837  1.1  mrg    EXP is the CALL_EXPR; TARGET is an optional place for us to store
   5838  1.1  mrg    the results.  */
   5839  1.1  mrg 
   5840  1.1  mrg static rtx
   5841  1.1  mrg expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
   5842  1.1  mrg 				       rtx target)
   5843  1.1  mrg {
   5844  1.1  mrg   rtx val, mem;
   5845  1.1  mrg 
   5846  1.1  mrg   /* Expand the operands.  */
   5847  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   5848  1.1  mrg   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
   5849  1.1  mrg 
   5850  1.1  mrg   return expand_sync_lock_test_and_set (target, mem, val);
   5851  1.1  mrg }
   5852  1.1  mrg 
   5853  1.1  mrg /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
   5854  1.1  mrg 
   5855  1.1  mrg static void
   5856  1.1  mrg expand_builtin_sync_lock_release (machine_mode mode, tree exp)
   5857  1.1  mrg {
   5858  1.1  mrg   rtx mem;
   5859  1.1  mrg 
   5860  1.1  mrg   /* Expand the operands.  */
   5861  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   5862  1.1  mrg 
   5863  1.1  mrg   expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
   5864  1.1  mrg }
   5865  1.1  mrg 
   5866  1.1  mrg /* Given an integer representing an ``enum memmodel'', verify its
   5867  1.1  mrg    correctness and return the memory model enum.  */
   5868  1.1  mrg 
   5869  1.1  mrg static enum memmodel
   5870  1.1  mrg get_memmodel (tree exp)
   5871  1.1  mrg {
   5872  1.1  mrg   /* If the parameter is not a constant, it's a run time value so we'll just
   5873  1.1  mrg      convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking.  */
   5874  1.1  mrg   if (TREE_CODE (exp) != INTEGER_CST)
   5875  1.1  mrg     return MEMMODEL_SEQ_CST;
   5876  1.1  mrg 
   5877  1.1  mrg   rtx op = expand_normal (exp);
   5878  1.1  mrg 
   5879  1.1  mrg   unsigned HOST_WIDE_INT val = INTVAL (op);
   5880  1.1  mrg   if (targetm.memmodel_check)
   5881  1.1  mrg     val = targetm.memmodel_check (val);
   5882  1.1  mrg   else if (val & ~MEMMODEL_MASK)
   5883  1.1  mrg     return MEMMODEL_SEQ_CST;
   5884  1.1  mrg 
   5885  1.1  mrg   /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
   5886  1.1  mrg   if (memmodel_base (val) >= MEMMODEL_LAST)
   5887  1.1  mrg     return MEMMODEL_SEQ_CST;
   5888  1.1  mrg 
   5889  1.1  mrg   /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
   5890  1.1  mrg      be conservative and promote consume to acquire.  */
   5891  1.1  mrg   if (val == MEMMODEL_CONSUME)
   5892  1.1  mrg     val = MEMMODEL_ACQUIRE;
   5893  1.1  mrg 
   5894  1.1  mrg   return (enum memmodel) val;
   5895  1.1  mrg }
   5896  1.1  mrg 
   5897  1.1  mrg /* Expand the __atomic_exchange intrinsic:
   5898  1.1  mrg    	TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
   5899  1.1  mrg    EXP is the CALL_EXPR.
   5900  1.1  mrg    TARGET is an optional place for us to store the results.  */
   5901  1.1  mrg 
   5902  1.1  mrg static rtx
   5903  1.1  mrg expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
   5904  1.1  mrg {
   5905  1.1  mrg   rtx val, mem;
   5906  1.1  mrg   enum memmodel model;
   5907  1.1  mrg 
   5908  1.1  mrg   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
   5909  1.1  mrg 
   5910  1.1  mrg   if (!flag_inline_atomics)
   5911  1.1  mrg     return NULL_RTX;
   5912  1.1  mrg 
   5913  1.1  mrg   /* Expand the operands.  */
   5914  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   5915  1.1  mrg   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
   5916  1.1  mrg 
   5917  1.1  mrg   return expand_atomic_exchange (target, mem, val, model);
   5918  1.1  mrg }
   5919  1.1  mrg 
   5920  1.1  mrg /* Expand the __atomic_compare_exchange intrinsic:
   5921  1.1  mrg    	bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
   5922  1.1  mrg 					TYPE desired, BOOL weak,
   5923  1.1  mrg 					enum memmodel success,
   5924  1.1  mrg 					enum memmodel failure)
   5925  1.1  mrg    EXP is the CALL_EXPR.
   5926  1.1  mrg    TARGET is an optional place for us to store the results.  */
   5927  1.1  mrg 
   5928  1.1  mrg static rtx
   5929  1.1  mrg expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
   5930  1.1  mrg 					rtx target)
   5931  1.1  mrg {
   5932  1.1  mrg   rtx expect, desired, mem, oldval;
   5933  1.1  mrg   rtx_code_label *label;
   5934  1.1  mrg   tree weak;
   5935  1.1  mrg   bool is_weak;
   5936  1.1  mrg 
   5937  1.1  mrg   memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
   5938  1.1  mrg   memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
   5939  1.1  mrg 
   5940  1.1  mrg   if (failure > success)
   5941  1.1  mrg     success = MEMMODEL_SEQ_CST;
   5942  1.1  mrg 
   5943  1.1  mrg   if (is_mm_release (failure) || is_mm_acq_rel (failure))
   5944  1.1  mrg     {
   5945  1.1  mrg       failure = MEMMODEL_SEQ_CST;
   5946  1.1  mrg       success = MEMMODEL_SEQ_CST;
   5947  1.1  mrg     }
   5948  1.1  mrg 
   5949  1.1  mrg 
   5950  1.1  mrg   if (!flag_inline_atomics)
   5951  1.1  mrg     return NULL_RTX;
   5952  1.1  mrg 
   5953  1.1  mrg   /* Expand the operands.  */
   5954  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   5955  1.1  mrg 
   5956  1.1  mrg   expect = expand_normal (CALL_EXPR_ARG (exp, 1));
   5957  1.1  mrg   expect = convert_memory_address (Pmode, expect);
   5958  1.1  mrg   expect = gen_rtx_MEM (mode, expect);
   5959  1.1  mrg   desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
   5960  1.1  mrg 
   5961  1.1  mrg   weak = CALL_EXPR_ARG (exp, 3);
   5962  1.1  mrg   is_weak = false;
   5963  1.1  mrg   if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
   5964  1.1  mrg     is_weak = true;
   5965  1.1  mrg 
   5966  1.1  mrg   if (target == const0_rtx)
   5967  1.1  mrg     target = NULL;
   5968  1.1  mrg 
   5969  1.1  mrg   /* Lest the rtl backend create a race condition with an imporoper store
   5970  1.1  mrg      to memory, always create a new pseudo for OLDVAL.  */
   5971  1.1  mrg   oldval = NULL;
   5972  1.1  mrg 
   5973  1.1  mrg   if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
   5974  1.1  mrg 				       is_weak, success, failure))
   5975  1.1  mrg     return NULL_RTX;
   5976  1.1  mrg 
   5977  1.1  mrg   /* Conditionally store back to EXPECT, lest we create a race condition
   5978  1.1  mrg      with an improper store to memory.  */
   5979  1.1  mrg   /* ??? With a rearrangement of atomics at the gimple level, we can handle
   5980  1.1  mrg      the normal case where EXPECT is totally private, i.e. a register.  At
   5981  1.1  mrg      which point the store can be unconditional.  */
   5982  1.1  mrg   label = gen_label_rtx ();
   5983  1.1  mrg   emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
   5984  1.1  mrg 			   GET_MODE (target), 1, label);
   5985  1.1  mrg   emit_move_insn (expect, oldval);
   5986  1.1  mrg   emit_label (label);
   5987  1.1  mrg 
   5988  1.1  mrg   return target;
   5989  1.1  mrg }
   5990  1.1  mrg 
   5991  1.1  mrg /* Helper function for expand_ifn_atomic_compare_exchange - expand
   5992  1.1  mrg    internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
   5993  1.1  mrg    call.  The weak parameter must be dropped to match the expected parameter
   5994  1.1  mrg    list and the expected argument changed from value to pointer to memory
   5995  1.1  mrg    slot.  */
   5996  1.1  mrg 
   5997  1.1  mrg static void
   5998  1.1  mrg expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
   5999  1.1  mrg {
   6000  1.1  mrg   unsigned int z;
   6001  1.1  mrg   vec<tree, va_gc> *vec;
   6002  1.1  mrg 
   6003  1.1  mrg   vec_alloc (vec, 5);
   6004  1.1  mrg   vec->quick_push (gimple_call_arg (call, 0));
   6005  1.1  mrg   tree expected = gimple_call_arg (call, 1);
   6006  1.1  mrg   rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
   6007  1.1  mrg 				      TREE_TYPE (expected));
   6008  1.1  mrg   rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
   6009  1.1  mrg   if (expd != x)
   6010  1.1  mrg     emit_move_insn (x, expd);
   6011  1.1  mrg   tree v = make_tree (TREE_TYPE (expected), x);
   6012  1.1  mrg   vec->quick_push (build1 (ADDR_EXPR,
   6013  1.1  mrg 			   build_pointer_type (TREE_TYPE (expected)), v));
   6014  1.1  mrg   vec->quick_push (gimple_call_arg (call, 2));
   6015  1.1  mrg   /* Skip the boolean weak parameter.  */
   6016  1.1  mrg   for (z = 4; z < 6; z++)
   6017  1.1  mrg     vec->quick_push (gimple_call_arg (call, z));
   6018  1.1  mrg   /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}.  */
   6019  1.1  mrg   unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
   6020  1.1  mrg   gcc_assert (bytes_log2 < 5);
   6021  1.1  mrg   built_in_function fncode
   6022  1.1  mrg     = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
   6023  1.1  mrg 			   + bytes_log2);
   6024  1.1  mrg   tree fndecl = builtin_decl_explicit (fncode);
   6025  1.1  mrg   tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
   6026  1.1  mrg 		    fndecl);
   6027  1.1  mrg   tree exp = build_call_vec (boolean_type_node, fn, vec);
   6028  1.1  mrg   tree lhs = gimple_call_lhs (call);
   6029  1.1  mrg   rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
   6030  1.1  mrg   if (lhs)
   6031  1.1  mrg     {
   6032  1.1  mrg       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
   6033  1.1  mrg       if (GET_MODE (boolret) != mode)
   6034  1.1  mrg 	boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
   6035  1.1  mrg       x = force_reg (mode, x);
   6036  1.1  mrg       write_complex_part (target, boolret, true);
   6037  1.1  mrg       write_complex_part (target, x, false);
   6038  1.1  mrg     }
   6039  1.1  mrg }
   6040  1.1  mrg 
   6041  1.1  mrg /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function.  */
   6042  1.1  mrg 
   6043  1.1  mrg void
   6044  1.1  mrg expand_ifn_atomic_compare_exchange (gcall *call)
   6045  1.1  mrg {
   6046  1.1  mrg   int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
   6047  1.1  mrg   gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
   6048  1.1  mrg   machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
   6049  1.1  mrg 
   6050  1.1  mrg   memmodel success = get_memmodel (gimple_call_arg (call, 4));
   6051  1.1  mrg   memmodel failure = get_memmodel (gimple_call_arg (call, 5));
   6052  1.1  mrg 
   6053  1.1  mrg   if (failure > success)
   6054  1.1  mrg     success = MEMMODEL_SEQ_CST;
   6055  1.1  mrg 
   6056  1.1  mrg   if (is_mm_release (failure) || is_mm_acq_rel (failure))
   6057  1.1  mrg     {
   6058  1.1  mrg       failure = MEMMODEL_SEQ_CST;
   6059  1.1  mrg       success = MEMMODEL_SEQ_CST;
   6060  1.1  mrg     }
   6061  1.1  mrg 
   6062  1.1  mrg   if (!flag_inline_atomics)
   6063  1.1  mrg     {
   6064  1.1  mrg       expand_ifn_atomic_compare_exchange_into_call (call, mode);
   6065  1.1  mrg       return;
   6066  1.1  mrg     }
   6067  1.1  mrg 
   6068  1.1  mrg   /* Expand the operands.  */
   6069  1.1  mrg   rtx mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
   6070  1.1  mrg 
   6071  1.1  mrg   rtx expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
   6072  1.1  mrg   rtx desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
   6073  1.1  mrg 
   6074  1.1  mrg   bool is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
   6075  1.1  mrg 
   6076  1.1  mrg   rtx boolret = NULL;
   6077  1.1  mrg   rtx oldval = NULL;
   6078  1.1  mrg 
   6079  1.1  mrg   if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
   6080  1.1  mrg 				       is_weak, success, failure))
   6081  1.1  mrg     {
   6082  1.1  mrg       expand_ifn_atomic_compare_exchange_into_call (call, mode);
   6083  1.1  mrg       return;
   6084  1.1  mrg     }
   6085  1.1  mrg 
   6086  1.1  mrg   tree lhs = gimple_call_lhs (call);
   6087  1.1  mrg   if (lhs)
   6088  1.1  mrg     {
   6089  1.1  mrg       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
   6090  1.1  mrg       if (GET_MODE (boolret) != mode)
   6091  1.1  mrg 	boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
   6092  1.1  mrg       write_complex_part (target, boolret, true);
   6093  1.1  mrg       write_complex_part (target, oldval, false);
   6094  1.1  mrg     }
   6095  1.1  mrg }
   6096  1.1  mrg 
   6097  1.1  mrg /* Expand the __atomic_load intrinsic:
   6098  1.1  mrg    	TYPE __atomic_load (TYPE *object, enum memmodel)
   6099  1.1  mrg    EXP is the CALL_EXPR.
   6100  1.1  mrg    TARGET is an optional place for us to store the results.  */
   6101  1.1  mrg 
   6102  1.1  mrg static rtx
   6103  1.1  mrg expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
   6104  1.1  mrg {
   6105  1.1  mrg   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
   6106  1.1  mrg   if (is_mm_release (model) || is_mm_acq_rel (model))
   6107  1.1  mrg     model = MEMMODEL_SEQ_CST;
   6108  1.1  mrg 
   6109  1.1  mrg   if (!flag_inline_atomics)
   6110  1.1  mrg     return NULL_RTX;
   6111  1.1  mrg 
   6112  1.1  mrg   /* Expand the operand.  */
   6113  1.1  mrg   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   6114  1.1  mrg 
   6115  1.1  mrg   return expand_atomic_load (target, mem, model);
   6116  1.1  mrg }
   6117  1.1  mrg 
   6118  1.1  mrg 
   6119  1.1  mrg /* Expand the __atomic_store intrinsic:
   6120  1.1  mrg    	void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
   6121  1.1  mrg    EXP is the CALL_EXPR.
   6122  1.1  mrg    TARGET is an optional place for us to store the results.  */
   6123  1.1  mrg 
   6124  1.1  mrg static rtx
   6125  1.1  mrg expand_builtin_atomic_store (machine_mode mode, tree exp)
   6126  1.1  mrg {
   6127  1.1  mrg   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
   6128  1.1  mrg   if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
   6129  1.1  mrg 	|| is_mm_release (model)))
   6130  1.1  mrg     model = MEMMODEL_SEQ_CST;
   6131  1.1  mrg 
   6132  1.1  mrg   if (!flag_inline_atomics)
   6133  1.1  mrg     return NULL_RTX;
   6134  1.1  mrg 
   6135  1.1  mrg   /* Expand the operands.  */
   6136  1.1  mrg   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   6137  1.1  mrg   rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
   6138  1.1  mrg 
   6139  1.1  mrg   return expand_atomic_store (mem, val, model, false);
   6140  1.1  mrg }
   6141  1.1  mrg 
   6142  1.1  mrg /* Expand the __atomic_fetch_XXX intrinsic:
   6143  1.1  mrg    	TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
   6144  1.1  mrg    EXP is the CALL_EXPR.
   6145  1.1  mrg    TARGET is an optional place for us to store the results.
   6146  1.1  mrg    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
   6147  1.1  mrg    FETCH_AFTER is true if returning the result of the operation.
   6148  1.1  mrg    FETCH_AFTER is false if returning the value before the operation.
   6149  1.1  mrg    IGNORE is true if the result is not used.
   6150  1.1  mrg    EXT_CALL is the correct builtin for an external call if this cannot be
   6151  1.1  mrg    resolved to an instruction sequence.  */
   6152  1.1  mrg 
   6153  1.1  mrg static rtx
   6154  1.1  mrg expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
   6155  1.1  mrg 				enum rtx_code code, bool fetch_after,
   6156  1.1  mrg 				bool ignore, enum built_in_function ext_call)
   6157  1.1  mrg {
   6158  1.1  mrg   rtx val, mem, ret;
   6159  1.1  mrg   enum memmodel model;
   6160  1.1  mrg   tree fndecl;
   6161  1.1  mrg   tree addr;
   6162  1.1  mrg 
   6163  1.1  mrg   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
   6164  1.1  mrg 
   6165  1.1  mrg   /* Expand the operands.  */
   6166  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   6167  1.1  mrg   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
   6168  1.1  mrg 
   6169  1.1  mrg   /* Only try generating instructions if inlining is turned on.  */
   6170  1.1  mrg   if (flag_inline_atomics)
   6171  1.1  mrg     {
   6172  1.1  mrg       ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
   6173  1.1  mrg       if (ret)
   6174  1.1  mrg 	return ret;
   6175  1.1  mrg     }
   6176  1.1  mrg 
   6177  1.1  mrg   /* Return if a different routine isn't needed for the library call.  */
   6178  1.1  mrg   if (ext_call == BUILT_IN_NONE)
   6179  1.1  mrg     return NULL_RTX;
   6180  1.1  mrg 
   6181  1.1  mrg   /* Change the call to the specified function.  */
   6182  1.1  mrg   fndecl = get_callee_fndecl (exp);
   6183  1.1  mrg   addr = CALL_EXPR_FN (exp);
   6184  1.1  mrg   STRIP_NOPS (addr);
   6185  1.1  mrg 
   6186  1.1  mrg   gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
   6187  1.1  mrg   TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
   6188  1.1  mrg 
   6189  1.1  mrg   /* If we will emit code after the call, the call cannot be a tail call.
   6190  1.1  mrg      If it is emitted as a tail call, a barrier is emitted after it, and
   6191  1.1  mrg      then all trailing code is removed.  */
   6192  1.1  mrg   if (!ignore)
   6193  1.1  mrg     CALL_EXPR_TAILCALL (exp) = 0;
   6194  1.1  mrg 
   6195  1.1  mrg   /* Expand the call here so we can emit trailing code.  */
   6196  1.1  mrg   ret = expand_call (exp, target, ignore);
   6197  1.1  mrg 
   6198  1.1  mrg   /* Replace the original function just in case it matters.  */
   6199  1.1  mrg   TREE_OPERAND (addr, 0) = fndecl;
   6200  1.1  mrg 
   6201  1.1  mrg   /* Then issue the arithmetic correction to return the right result.  */
   6202  1.1  mrg   if (!ignore)
   6203  1.1  mrg     {
   6204  1.1  mrg       if (code == NOT)
   6205  1.1  mrg 	{
   6206  1.1  mrg 	  ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
   6207  1.1  mrg 				     OPTAB_LIB_WIDEN);
   6208  1.1  mrg 	  ret = expand_simple_unop (mode, NOT, ret, target, true);
   6209  1.1  mrg 	}
   6210  1.1  mrg       else
   6211  1.1  mrg 	ret = expand_simple_binop (mode, code, ret, val, target, true,
   6212  1.1  mrg 				   OPTAB_LIB_WIDEN);
   6213  1.1  mrg     }
   6214  1.1  mrg   return ret;
   6215  1.1  mrg }
   6216  1.1  mrg 
   6217  1.1  mrg /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function.  */
   6218  1.1  mrg 
   6219  1.1  mrg void
   6220  1.1  mrg expand_ifn_atomic_bit_test_and (gcall *call)
   6221  1.1  mrg {
   6222  1.1  mrg   tree ptr = gimple_call_arg (call, 0);
   6223  1.1  mrg   tree bit = gimple_call_arg (call, 1);
   6224  1.1  mrg   tree flag = gimple_call_arg (call, 2);
   6225  1.1  mrg   tree lhs = gimple_call_lhs (call);
   6226  1.1  mrg   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
   6227  1.1  mrg   machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
   6228  1.1  mrg   enum rtx_code code;
   6229  1.1  mrg   optab optab;
   6230  1.1  mrg   class expand_operand ops[5];
   6231  1.1  mrg 
   6232  1.1  mrg   gcc_assert (flag_inline_atomics);
   6233  1.1  mrg 
   6234  1.1  mrg   if (gimple_call_num_args (call) == 5)
   6235  1.1  mrg     model = get_memmodel (gimple_call_arg (call, 3));
   6236  1.1  mrg 
   6237  1.1  mrg   rtx mem = get_builtin_sync_mem (ptr, mode);
   6238  1.1  mrg   rtx val = expand_expr_force_mode (bit, mode);
   6239  1.1  mrg 
   6240  1.1  mrg   switch (gimple_call_internal_fn (call))
   6241  1.1  mrg     {
   6242  1.1  mrg     case IFN_ATOMIC_BIT_TEST_AND_SET:
   6243  1.1  mrg       code = IOR;
   6244  1.1  mrg       optab = atomic_bit_test_and_set_optab;
   6245  1.1  mrg       break;
   6246  1.1  mrg     case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
   6247  1.1  mrg       code = XOR;
   6248  1.1  mrg       optab = atomic_bit_test_and_complement_optab;
   6249  1.1  mrg       break;
   6250  1.1  mrg     case IFN_ATOMIC_BIT_TEST_AND_RESET:
   6251  1.1  mrg       code = AND;
   6252  1.1  mrg       optab = atomic_bit_test_and_reset_optab;
   6253  1.1  mrg       break;
   6254  1.1  mrg     default:
   6255  1.1  mrg       gcc_unreachable ();
   6256  1.1  mrg     }
   6257  1.1  mrg 
   6258  1.1  mrg   if (lhs == NULL_TREE)
   6259  1.1  mrg     {
   6260  1.1  mrg       rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
   6261  1.1  mrg 				      val, NULL_RTX, true, OPTAB_DIRECT);
   6262  1.1  mrg       if (code == AND)
   6263  1.1  mrg 	val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
   6264  1.1  mrg       if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
   6265  1.1  mrg 	return;
   6266  1.1  mrg     }
   6267  1.1  mrg 
   6268  1.1  mrg   rtx target;
   6269  1.1  mrg   if (lhs)
   6270  1.1  mrg     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
   6271  1.1  mrg   else
   6272  1.1  mrg     target = gen_reg_rtx (mode);
   6273  1.1  mrg   enum insn_code icode = direct_optab_handler (optab, mode);
   6274  1.1  mrg   gcc_assert (icode != CODE_FOR_nothing);
   6275  1.1  mrg   create_output_operand (&ops[0], target, mode);
   6276  1.1  mrg   create_fixed_operand (&ops[1], mem);
   6277  1.1  mrg   create_convert_operand_to (&ops[2], val, mode, true);
   6278  1.1  mrg   create_integer_operand (&ops[3], model);
   6279  1.1  mrg   create_integer_operand (&ops[4], integer_onep (flag));
   6280  1.1  mrg   if (maybe_expand_insn (icode, 5, ops))
   6281  1.1  mrg     return;
   6282  1.1  mrg 
   6283  1.1  mrg   rtx bitval = val;
   6284  1.1  mrg   val = expand_simple_binop (mode, ASHIFT, const1_rtx,
   6285  1.1  mrg 			     val, NULL_RTX, true, OPTAB_DIRECT);
   6286  1.1  mrg   rtx maskval = val;
   6287  1.1  mrg   if (code == AND)
   6288  1.1  mrg     val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
   6289  1.1  mrg   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
   6290  1.1  mrg 				       code, model, false);
   6291  1.1  mrg   if (!result)
   6292  1.1  mrg     {
   6293  1.1  mrg       bool is_atomic = gimple_call_num_args (call) == 5;
   6294  1.1  mrg       tree tcall = gimple_call_arg (call, 3 + is_atomic);
   6295  1.1  mrg       tree fndecl = gimple_call_addr_fndecl (tcall);
   6296  1.1  mrg       tree type = TREE_TYPE (TREE_TYPE (fndecl));
   6297  1.1  mrg       tree exp = build_call_nary (type, tcall, 2 + is_atomic, ptr,
   6298  1.1  mrg 				  make_tree (type, val),
   6299  1.1  mrg 				  is_atomic
   6300  1.1  mrg 				  ? gimple_call_arg (call, 3)
   6301  1.1  mrg 				  : integer_zero_node);
   6302  1.1  mrg       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
   6303  1.1  mrg 			       mode, !lhs);
   6304  1.1  mrg     }
   6305  1.1  mrg   if (!lhs)
   6306  1.1  mrg     return;
   6307  1.1  mrg   if (integer_onep (flag))
   6308  1.1  mrg     {
   6309  1.1  mrg       result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
   6310  1.1  mrg 				    NULL_RTX, true, OPTAB_DIRECT);
   6311  1.1  mrg       result = expand_simple_binop (mode, AND, result, const1_rtx, target,
   6312  1.1  mrg 				    true, OPTAB_DIRECT);
   6313  1.1  mrg     }
   6314  1.1  mrg   else
   6315  1.1  mrg     result = expand_simple_binop (mode, AND, result, maskval, target, true,
   6316  1.1  mrg 				  OPTAB_DIRECT);
   6317  1.1  mrg   if (result != target)
   6318  1.1  mrg     emit_move_insn (target, result);
   6319  1.1  mrg }
   6320  1.1  mrg 
   6321  1.1  mrg /* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function.  */
   6322  1.1  mrg 
   6323  1.1  mrg void
   6324  1.1  mrg expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
   6325  1.1  mrg {
   6326  1.1  mrg   tree cmp = gimple_call_arg (call, 0);
   6327  1.1  mrg   tree ptr = gimple_call_arg (call, 1);
   6328  1.1  mrg   tree arg = gimple_call_arg (call, 2);
   6329  1.1  mrg   tree lhs = gimple_call_lhs (call);
   6330  1.1  mrg   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
   6331  1.1  mrg   machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
   6332  1.1  mrg   optab optab;
   6333  1.1  mrg   rtx_code code;
   6334  1.1  mrg   class expand_operand ops[5];
   6335  1.1  mrg 
   6336  1.1  mrg   gcc_assert (flag_inline_atomics);
   6337  1.1  mrg 
   6338  1.1  mrg   if (gimple_call_num_args (call) == 5)
   6339  1.1  mrg     model = get_memmodel (gimple_call_arg (call, 3));
   6340  1.1  mrg 
   6341  1.1  mrg   rtx mem = get_builtin_sync_mem (ptr, mode);
   6342  1.1  mrg   rtx op = expand_expr_force_mode (arg, mode);
   6343  1.1  mrg 
   6344  1.1  mrg   switch (gimple_call_internal_fn (call))
   6345  1.1  mrg     {
   6346  1.1  mrg     case IFN_ATOMIC_ADD_FETCH_CMP_0:
   6347  1.1  mrg       code = PLUS;
   6348  1.1  mrg       optab = atomic_add_fetch_cmp_0_optab;
   6349  1.1  mrg       break;
   6350  1.1  mrg     case IFN_ATOMIC_SUB_FETCH_CMP_0:
   6351  1.1  mrg       code = MINUS;
   6352  1.1  mrg       optab = atomic_sub_fetch_cmp_0_optab;
   6353  1.1  mrg       break;
   6354  1.1  mrg     case IFN_ATOMIC_AND_FETCH_CMP_0:
   6355  1.1  mrg       code = AND;
   6356  1.1  mrg       optab = atomic_and_fetch_cmp_0_optab;
   6357  1.1  mrg       break;
   6358  1.1  mrg     case IFN_ATOMIC_OR_FETCH_CMP_0:
   6359  1.1  mrg       code = IOR;
   6360  1.1  mrg       optab = atomic_or_fetch_cmp_0_optab;
   6361  1.1  mrg       break;
   6362  1.1  mrg     case IFN_ATOMIC_XOR_FETCH_CMP_0:
   6363  1.1  mrg       code = XOR;
   6364  1.1  mrg       optab = atomic_xor_fetch_cmp_0_optab;
   6365  1.1  mrg       break;
   6366  1.1  mrg     default:
   6367  1.1  mrg       gcc_unreachable ();
   6368  1.1  mrg     }
   6369  1.1  mrg 
   6370  1.1  mrg   enum rtx_code comp = UNKNOWN;
   6371  1.1  mrg   switch (tree_to_uhwi (cmp))
   6372  1.1  mrg     {
   6373  1.1  mrg     case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
   6374  1.1  mrg     case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
   6375  1.1  mrg     case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
   6376  1.1  mrg     case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
   6377  1.1  mrg     case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
   6378  1.1  mrg     case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
   6379  1.1  mrg     default: gcc_unreachable ();
   6380  1.1  mrg     }
   6381  1.1  mrg 
   6382  1.1  mrg   rtx target;
   6383  1.1  mrg   if (lhs == NULL_TREE)
   6384  1.1  mrg     target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
   6385  1.1  mrg   else
   6386  1.1  mrg     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
   6387  1.1  mrg   enum insn_code icode = direct_optab_handler (optab, mode);
   6388  1.1  mrg   gcc_assert (icode != CODE_FOR_nothing);
   6389  1.1  mrg   create_output_operand (&ops[0], target, TYPE_MODE (boolean_type_node));
   6390  1.1  mrg   create_fixed_operand (&ops[1], mem);
   6391  1.1  mrg   create_convert_operand_to (&ops[2], op, mode, true);
   6392  1.1  mrg   create_integer_operand (&ops[3], model);
   6393  1.1  mrg   create_integer_operand (&ops[4], comp);
   6394  1.1  mrg   if (maybe_expand_insn (icode, 5, ops))
   6395  1.1  mrg     return;
   6396  1.1  mrg 
   6397  1.1  mrg   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
   6398  1.1  mrg 				       code, model, true);
   6399  1.1  mrg   if (!result)
   6400  1.1  mrg     {
   6401  1.1  mrg       bool is_atomic = gimple_call_num_args (call) == 5;
   6402  1.1  mrg       tree tcall = gimple_call_arg (call, 3 + is_atomic);
   6403  1.1  mrg       tree fndecl = gimple_call_addr_fndecl (tcall);
   6404  1.1  mrg       tree type = TREE_TYPE (TREE_TYPE (fndecl));
   6405  1.1  mrg       tree exp = build_call_nary (type, tcall,
   6406  1.1  mrg 				  2 + is_atomic, ptr, arg,
   6407  1.1  mrg 				  is_atomic
   6408  1.1  mrg 				  ? gimple_call_arg (call, 3)
   6409  1.1  mrg 				  : integer_zero_node);
   6410  1.1  mrg       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
   6411  1.1  mrg 			       mode, !lhs);
   6412  1.1  mrg     }
   6413  1.1  mrg 
   6414  1.1  mrg   if (lhs)
   6415  1.1  mrg     {
   6416  1.1  mrg       result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
   6417  1.1  mrg 				      0, 1);
   6418  1.1  mrg       if (result != target)
   6419  1.1  mrg 	emit_move_insn (target, result);
   6420  1.1  mrg     }
   6421  1.1  mrg }
   6422  1.1  mrg 
   6423  1.1  mrg /* Expand an atomic clear operation.
   6424  1.1  mrg 	void _atomic_clear (BOOL *obj, enum memmodel)
   6425  1.1  mrg    EXP is the call expression.  */
   6426  1.1  mrg 
   6427  1.1  mrg static rtx
   6428  1.1  mrg expand_builtin_atomic_clear (tree exp)
   6429  1.1  mrg {
   6430  1.1  mrg   machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
   6431  1.1  mrg   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   6432  1.1  mrg   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
   6433  1.1  mrg 
   6434  1.1  mrg   if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
   6435  1.1  mrg     model = MEMMODEL_SEQ_CST;
   6436  1.1  mrg 
   6437  1.1  mrg   /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
   6438  1.1  mrg      Failing that, a store is issued by __atomic_store.  The only way this can
   6439  1.1  mrg      fail is if the bool type is larger than a word size.  Unlikely, but
   6440  1.1  mrg      handle it anyway for completeness.  Assume a single threaded model since
   6441  1.1  mrg      there is no atomic support in this case, and no barriers are required.  */
   6442  1.1  mrg   rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
   6443  1.1  mrg   if (!ret)
   6444  1.1  mrg     emit_move_insn (mem, const0_rtx);
   6445  1.1  mrg   return const0_rtx;
   6446  1.1  mrg }
   6447  1.1  mrg 
   6448  1.1  mrg /* Expand an atomic test_and_set operation.
   6449  1.1  mrg 	bool _atomic_test_and_set (BOOL *obj, enum memmodel)
   6450  1.1  mrg    EXP is the call expression.  */
   6451  1.1  mrg 
   6452  1.1  mrg static rtx
   6453  1.1  mrg expand_builtin_atomic_test_and_set (tree exp, rtx target)
   6454  1.1  mrg {
   6455  1.1  mrg   rtx mem;
   6456  1.1  mrg   enum memmodel model;
   6457  1.1  mrg   machine_mode mode;
   6458  1.1  mrg 
   6459  1.1  mrg   mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
   6460  1.1  mrg   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   6461  1.1  mrg   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
   6462  1.1  mrg 
   6463  1.1  mrg   return expand_atomic_test_and_set (target, mem, model);
   6464  1.1  mrg }
   6465  1.1  mrg 
   6466  1.1  mrg 
   6467  1.1  mrg /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
   6468  1.1  mrg    this architecture.  If ARG1 is NULL, use typical alignment for size ARG0.  */
   6469  1.1  mrg 
   6470  1.1  mrg static tree
   6471  1.1  mrg fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
   6472  1.1  mrg {
   6473  1.1  mrg   int size;
   6474  1.1  mrg   machine_mode mode;
   6475  1.1  mrg   unsigned int mode_align, type_align;
   6476  1.1  mrg 
   6477  1.1  mrg   if (TREE_CODE (arg0) != INTEGER_CST)
   6478  1.1  mrg     return NULL_TREE;
   6479  1.1  mrg 
   6480  1.1  mrg   /* We need a corresponding integer mode for the access to be lock-free.  */
   6481  1.1  mrg   size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
   6482  1.1  mrg   if (!int_mode_for_size (size, 0).exists (&mode))
   6483  1.1  mrg     return boolean_false_node;
   6484  1.1  mrg 
   6485  1.1  mrg   mode_align = GET_MODE_ALIGNMENT (mode);
   6486  1.1  mrg 
   6487  1.1  mrg   if (TREE_CODE (arg1) == INTEGER_CST)
   6488  1.1  mrg     {
   6489  1.1  mrg       unsigned HOST_WIDE_INT val = UINTVAL (expand_normal (arg1));
   6490  1.1  mrg 
   6491  1.1  mrg       /* Either this argument is null, or it's a fake pointer encoding
   6492  1.1  mrg          the alignment of the object.  */
   6493  1.1  mrg       val = least_bit_hwi (val);
   6494  1.1  mrg       val *= BITS_PER_UNIT;
   6495  1.1  mrg 
   6496  1.1  mrg       if (val == 0 || mode_align < val)
   6497  1.1  mrg         type_align = mode_align;
   6498  1.1  mrg       else
   6499  1.1  mrg         type_align = val;
   6500  1.1  mrg     }
   6501  1.1  mrg   else
   6502  1.1  mrg     {
   6503  1.1  mrg       tree ttype = TREE_TYPE (arg1);
   6504  1.1  mrg 
   6505  1.1  mrg       /* This function is usually invoked and folded immediately by the front
   6506  1.1  mrg 	 end before anything else has a chance to look at it.  The pointer
   6507  1.1  mrg 	 parameter at this point is usually cast to a void *, so check for that
   6508  1.1  mrg 	 and look past the cast.  */
   6509  1.1  mrg       if (CONVERT_EXPR_P (arg1)
   6510  1.1  mrg 	  && POINTER_TYPE_P (ttype)
   6511  1.1  mrg 	  && VOID_TYPE_P (TREE_TYPE (ttype))
   6512  1.1  mrg 	  && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
   6513  1.1  mrg 	arg1 = TREE_OPERAND (arg1, 0);
   6514  1.1  mrg 
   6515  1.1  mrg       ttype = TREE_TYPE (arg1);
   6516  1.1  mrg       gcc_assert (POINTER_TYPE_P (ttype));
   6517  1.1  mrg 
   6518  1.1  mrg       /* Get the underlying type of the object.  */
   6519  1.1  mrg       ttype = TREE_TYPE (ttype);
   6520  1.1  mrg       type_align = TYPE_ALIGN (ttype);
   6521  1.1  mrg     }
   6522  1.1  mrg 
   6523  1.1  mrg   /* If the object has smaller alignment, the lock free routines cannot
   6524  1.1  mrg      be used.  */
   6525  1.1  mrg   if (type_align < mode_align)
   6526  1.1  mrg     return boolean_false_node;
   6527  1.1  mrg 
   6528  1.1  mrg   /* Check if a compare_and_swap pattern exists for the mode which represents
   6529  1.1  mrg      the required size.  The pattern is not allowed to fail, so the existence
   6530  1.1  mrg      of the pattern indicates support is present.  Also require that an
   6531  1.1  mrg      atomic load exists for the required size.  */
   6532  1.1  mrg   if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
   6533  1.1  mrg     return boolean_true_node;
   6534  1.1  mrg   else
   6535  1.1  mrg     return boolean_false_node;
   6536  1.1  mrg }
   6537  1.1  mrg 
   6538  1.1  mrg /* Return true if the parameters to call EXP represent an object which will
   6539  1.1  mrg    always generate lock free instructions.  The first argument represents the
   6540  1.1  mrg    size of the object, and the second parameter is a pointer to the object
   6541  1.1  mrg    itself.  If NULL is passed for the object, then the result is based on
   6542  1.1  mrg    typical alignment for an object of the specified size.  Otherwise return
   6543  1.1  mrg    false.  */
   6544  1.1  mrg 
   6545  1.1  mrg static rtx
   6546  1.1  mrg expand_builtin_atomic_always_lock_free (tree exp)
   6547  1.1  mrg {
   6548  1.1  mrg   tree size;
   6549  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   6550  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 1);
   6551  1.1  mrg 
   6552  1.1  mrg   if (TREE_CODE (arg0) != INTEGER_CST)
   6553  1.1  mrg     {
   6554  1.1  mrg       error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
   6555  1.1  mrg       return const0_rtx;
   6556  1.1  mrg     }
   6557  1.1  mrg 
   6558  1.1  mrg   size = fold_builtin_atomic_always_lock_free (arg0, arg1);
   6559  1.1  mrg   if (size == boolean_true_node)
   6560  1.1  mrg     return const1_rtx;
   6561  1.1  mrg   return const0_rtx;
   6562  1.1  mrg }
   6563  1.1  mrg 
   6564  1.1  mrg /* Return a one or zero if it can be determined that object ARG1 of size ARG
   6565  1.1  mrg    is lock free on this architecture.  */
   6566  1.1  mrg 
   6567  1.1  mrg static tree
   6568  1.1  mrg fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
   6569  1.1  mrg {
   6570  1.1  mrg   if (!flag_inline_atomics)
   6571  1.1  mrg     return NULL_TREE;
   6572  1.1  mrg 
   6573  1.1  mrg   /* If it isn't always lock free, don't generate a result.  */
   6574  1.1  mrg   if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
   6575  1.1  mrg     return boolean_true_node;
   6576  1.1  mrg 
   6577  1.1  mrg   return NULL_TREE;
   6578  1.1  mrg }
   6579  1.1  mrg 
   6580  1.1  mrg /* Return true if the parameters to call EXP represent an object which will
   6581  1.1  mrg    always generate lock free instructions.  The first argument represents the
   6582  1.1  mrg    size of the object, and the second parameter is a pointer to the object
   6583  1.1  mrg    itself.  If NULL is passed for the object, then the result is based on
   6584  1.1  mrg    typical alignment for an object of the specified size.  Otherwise return
   6585  1.1  mrg    NULL*/
   6586  1.1  mrg 
   6587  1.1  mrg static rtx
   6588  1.1  mrg expand_builtin_atomic_is_lock_free (tree exp)
   6589  1.1  mrg {
   6590  1.1  mrg   tree size;
   6591  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   6592  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 1);
   6593  1.1  mrg 
   6594  1.1  mrg   if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
   6595  1.1  mrg     {
   6596  1.1  mrg       error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
   6597  1.1  mrg       return NULL_RTX;
   6598  1.1  mrg     }
   6599  1.1  mrg 
   6600  1.1  mrg   if (!flag_inline_atomics)
   6601  1.1  mrg     return NULL_RTX;
   6602  1.1  mrg 
   6603  1.1  mrg   /* If the value is known at compile time, return the RTX for it.  */
   6604  1.1  mrg   size = fold_builtin_atomic_is_lock_free (arg0, arg1);
   6605  1.1  mrg   if (size == boolean_true_node)
   6606  1.1  mrg     return const1_rtx;
   6607  1.1  mrg 
   6608  1.1  mrg   return NULL_RTX;
   6609  1.1  mrg }
   6610  1.1  mrg 
   6611  1.1  mrg /* Expand the __atomic_thread_fence intrinsic:
   6612  1.1  mrg    	void __atomic_thread_fence (enum memmodel)
   6613  1.1  mrg    EXP is the CALL_EXPR.  */
   6614  1.1  mrg 
   6615  1.1  mrg static void
   6616  1.1  mrg expand_builtin_atomic_thread_fence (tree exp)
   6617  1.1  mrg {
   6618  1.1  mrg   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
   6619  1.1  mrg   expand_mem_thread_fence (model);
   6620  1.1  mrg }
   6621  1.1  mrg 
   6622  1.1  mrg /* Expand the __atomic_signal_fence intrinsic:
   6623  1.1  mrg    	void __atomic_signal_fence (enum memmodel)
   6624  1.1  mrg    EXP is the CALL_EXPR.  */
   6625  1.1  mrg 
   6626  1.1  mrg static void
   6627  1.1  mrg expand_builtin_atomic_signal_fence (tree exp)
   6628  1.1  mrg {
   6629  1.1  mrg   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
   6630  1.1  mrg   expand_mem_signal_fence (model);
   6631  1.1  mrg }
   6632  1.1  mrg 
   6633  1.1  mrg /* Expand the __sync_synchronize intrinsic.  */
   6634  1.1  mrg 
   6635  1.1  mrg static void
   6636  1.1  mrg expand_builtin_sync_synchronize (void)
   6637  1.1  mrg {
   6638  1.1  mrg   expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
   6639  1.1  mrg }
   6640  1.1  mrg 
   6641  1.1  mrg static rtx
   6642  1.1  mrg expand_builtin_thread_pointer (tree exp, rtx target)
   6643  1.1  mrg {
   6644  1.1  mrg   enum insn_code icode;
   6645  1.1  mrg   if (!validate_arglist (exp, VOID_TYPE))
   6646  1.1  mrg     return const0_rtx;
   6647  1.1  mrg   icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
   6648  1.1  mrg   if (icode != CODE_FOR_nothing)
   6649  1.1  mrg     {
   6650  1.1  mrg       class expand_operand op;
   6651  1.1  mrg       /* If the target is not sutitable then create a new target. */
   6652  1.1  mrg       if (target == NULL_RTX
   6653  1.1  mrg 	  || !REG_P (target)
   6654  1.1  mrg 	  || GET_MODE (target) != Pmode)
   6655  1.1  mrg 	target = gen_reg_rtx (Pmode);
   6656  1.1  mrg       create_output_operand (&op, target, Pmode);
   6657  1.1  mrg       expand_insn (icode, 1, &op);
   6658  1.1  mrg       return target;
   6659  1.1  mrg     }
   6660  1.1  mrg   error ("%<__builtin_thread_pointer%> is not supported on this target");
   6661  1.1  mrg   return const0_rtx;
   6662  1.1  mrg }
   6663  1.1  mrg 
   6664  1.1  mrg static void
   6665  1.1  mrg expand_builtin_set_thread_pointer (tree exp)
   6666  1.1  mrg {
   6667  1.1  mrg   enum insn_code icode;
   6668  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   6669  1.1  mrg     return;
   6670  1.1  mrg   icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
   6671  1.1  mrg   if (icode != CODE_FOR_nothing)
   6672  1.1  mrg     {
   6673  1.1  mrg       class expand_operand op;
   6674  1.1  mrg       rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
   6675  1.1  mrg 			     Pmode, EXPAND_NORMAL);
   6676  1.1  mrg       create_input_operand (&op, val, Pmode);
   6677  1.1  mrg       expand_insn (icode, 1, &op);
   6678  1.1  mrg       return;
   6679  1.1  mrg     }
   6680  1.1  mrg   error ("%<__builtin_set_thread_pointer%> is not supported on this target");
   6681  1.1  mrg }
   6682  1.1  mrg 
   6683  1.1  mrg 
   6684  1.1  mrg /* Emit code to restore the current value of stack.  */
   6686  1.1  mrg 
   6687  1.1  mrg static void
   6688  1.1  mrg expand_stack_restore (tree var)
   6689  1.1  mrg {
   6690  1.1  mrg   rtx_insn *prev;
   6691  1.1  mrg   rtx sa = expand_normal (var);
   6692  1.1  mrg 
   6693  1.1  mrg   sa = convert_memory_address (Pmode, sa);
   6694  1.1  mrg 
   6695  1.1  mrg   prev = get_last_insn ();
   6696  1.1  mrg   emit_stack_restore (SAVE_BLOCK, sa);
   6697  1.1  mrg 
   6698  1.1  mrg   record_new_stack_level ();
   6699  1.1  mrg 
   6700  1.1  mrg   fixup_args_size_notes (prev, get_last_insn (), 0);
   6701  1.1  mrg }
   6702  1.1  mrg 
   6703  1.1  mrg /* Emit code to save the current value of stack.  */
   6704  1.1  mrg 
   6705  1.1  mrg static rtx
   6706  1.1  mrg expand_stack_save (void)
   6707  1.1  mrg {
   6708  1.1  mrg   rtx ret = NULL_RTX;
   6709  1.1  mrg 
   6710  1.1  mrg   emit_stack_save (SAVE_BLOCK, &ret);
   6711  1.1  mrg   return ret;
   6712  1.1  mrg }
   6713  1.1  mrg 
   6714  1.1  mrg /* Emit code to get the openacc gang, worker or vector id or size.  */
   6715  1.1  mrg 
   6716  1.1  mrg static rtx
   6717  1.1  mrg expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
   6718  1.1  mrg {
   6719  1.1  mrg   const char *name;
   6720  1.1  mrg   rtx fallback_retval;
   6721  1.1  mrg   rtx_insn *(*gen_fn) (rtx, rtx);
   6722  1.1  mrg   switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
   6723  1.1  mrg     {
   6724  1.1  mrg     case BUILT_IN_GOACC_PARLEVEL_ID:
   6725  1.1  mrg       name = "__builtin_goacc_parlevel_id";
   6726  1.1  mrg       fallback_retval = const0_rtx;
   6727  1.1  mrg       gen_fn = targetm.gen_oacc_dim_pos;
   6728  1.1  mrg       break;
   6729  1.1  mrg     case BUILT_IN_GOACC_PARLEVEL_SIZE:
   6730  1.1  mrg       name = "__builtin_goacc_parlevel_size";
   6731  1.1  mrg       fallback_retval = const1_rtx;
   6732  1.1  mrg       gen_fn = targetm.gen_oacc_dim_size;
   6733  1.1  mrg       break;
   6734  1.1  mrg     default:
   6735  1.1  mrg       gcc_unreachable ();
   6736  1.1  mrg     }
   6737  1.1  mrg 
   6738  1.1  mrg   if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
   6739  1.1  mrg     {
   6740  1.1  mrg       error ("%qs only supported in OpenACC code", name);
   6741  1.1  mrg       return const0_rtx;
   6742  1.1  mrg     }
   6743  1.1  mrg 
   6744  1.1  mrg   tree arg = CALL_EXPR_ARG (exp, 0);
   6745  1.1  mrg   if (TREE_CODE (arg) != INTEGER_CST)
   6746  1.1  mrg     {
   6747  1.1  mrg       error ("non-constant argument 0 to %qs", name);
   6748  1.1  mrg       return const0_rtx;
   6749  1.1  mrg     }
   6750  1.1  mrg 
   6751  1.1  mrg   int dim = TREE_INT_CST_LOW (arg);
   6752  1.1  mrg   switch (dim)
   6753  1.1  mrg     {
   6754  1.1  mrg     case GOMP_DIM_GANG:
   6755  1.1  mrg     case GOMP_DIM_WORKER:
   6756  1.1  mrg     case GOMP_DIM_VECTOR:
   6757  1.1  mrg       break;
   6758  1.1  mrg     default:
   6759  1.1  mrg       error ("illegal argument 0 to %qs", name);
   6760  1.1  mrg       return const0_rtx;
   6761  1.1  mrg     }
   6762  1.1  mrg 
   6763  1.1  mrg   if (ignore)
   6764  1.1  mrg     return target;
   6765  1.1  mrg 
   6766  1.1  mrg   if (target == NULL_RTX)
   6767  1.1  mrg     target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
   6768  1.1  mrg 
   6769  1.1  mrg   if (!targetm.have_oacc_dim_size ())
   6770  1.1  mrg     {
   6771  1.1  mrg       emit_move_insn (target, fallback_retval);
   6772  1.1  mrg       return target;
   6773  1.1  mrg     }
   6774  1.1  mrg 
   6775  1.1  mrg   rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
   6776  1.1  mrg   emit_insn (gen_fn (reg, GEN_INT (dim)));
   6777  1.1  mrg   if (reg != target)
   6778  1.1  mrg     emit_move_insn (target, reg);
   6779  1.1  mrg 
   6780  1.1  mrg   return target;
   6781  1.1  mrg }
   6782  1.1  mrg 
   6783  1.1  mrg /* Expand a string compare operation using a sequence of char comparison
   6784  1.1  mrg    to get rid of the calling overhead, with result going to TARGET if
   6785  1.1  mrg    that's convenient.
   6786  1.1  mrg 
   6787  1.1  mrg    VAR_STR is the variable string source;
   6788  1.1  mrg    CONST_STR is the constant string source;
   6789  1.1  mrg    LENGTH is the number of chars to compare;
   6790  1.1  mrg    CONST_STR_N indicates which source string is the constant string;
   6791  1.1  mrg    IS_MEMCMP indicates whether it's a memcmp or strcmp.
   6792  1.1  mrg 
   6793  1.1  mrg    to: (assume const_str_n is 2, i.e., arg2 is a constant string)
   6794  1.1  mrg 
   6795  1.1  mrg    target = (int) (unsigned char) var_str[0]
   6796  1.1  mrg 	    - (int) (unsigned char) const_str[0];
   6797  1.1  mrg    if (target != 0)
   6798  1.1  mrg      goto ne_label;
   6799  1.1  mrg      ...
   6800  1.1  mrg    target = (int) (unsigned char) var_str[length - 2]
   6801  1.1  mrg 	    - (int) (unsigned char) const_str[length - 2];
   6802  1.1  mrg    if (target != 0)
   6803  1.1  mrg      goto ne_label;
   6804  1.1  mrg    target = (int) (unsigned char) var_str[length - 1]
   6805  1.1  mrg 	    - (int) (unsigned char) const_str[length - 1];
   6806  1.1  mrg    ne_label:
   6807  1.1  mrg   */
   6808  1.1  mrg 
   6809  1.1  mrg static rtx
   6810  1.1  mrg inline_string_cmp (rtx target, tree var_str, const char *const_str,
   6811  1.1  mrg 		   unsigned HOST_WIDE_INT length,
   6812  1.1  mrg 		   int const_str_n, machine_mode mode)
   6813  1.1  mrg {
   6814  1.1  mrg   HOST_WIDE_INT offset = 0;
   6815  1.1  mrg   rtx var_rtx_array
   6816  1.1  mrg     = get_memory_rtx (var_str, build_int_cst (unsigned_type_node,length));
   6817  1.1  mrg   rtx var_rtx = NULL_RTX;
   6818  1.1  mrg   rtx const_rtx = NULL_RTX;
   6819  1.1  mrg   rtx result = target ? target : gen_reg_rtx (mode);
   6820  1.1  mrg   rtx_code_label *ne_label = gen_label_rtx ();
   6821  1.1  mrg   tree unit_type_node = unsigned_char_type_node;
   6822  1.1  mrg   scalar_int_mode unit_mode
   6823  1.1  mrg     = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
   6824  1.1  mrg 
   6825  1.1  mrg   start_sequence ();
   6826  1.1  mrg 
   6827  1.1  mrg   for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
   6828  1.1  mrg     {
   6829  1.1  mrg       var_rtx
   6830  1.1  mrg 	= adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
   6831  1.1  mrg       const_rtx = c_readstr (const_str + offset, unit_mode);
   6832  1.1  mrg       rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
   6833  1.1  mrg       rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
   6834  1.1  mrg 
   6835  1.1  mrg       op0 = convert_modes (mode, unit_mode, op0, 1);
   6836  1.1  mrg       op1 = convert_modes (mode, unit_mode, op1, 1);
   6837  1.1  mrg       result = expand_simple_binop (mode, MINUS, op0, op1,
   6838  1.1  mrg 				    result, 1, OPTAB_WIDEN);
   6839  1.1  mrg       if (i < length - 1)
   6840  1.1  mrg 	emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
   6841  1.1  mrg 	    			 mode, true, ne_label);
   6842  1.1  mrg       offset += GET_MODE_SIZE (unit_mode);
   6843  1.1  mrg     }
   6844  1.1  mrg 
   6845  1.1  mrg   emit_label (ne_label);
   6846  1.1  mrg   rtx_insn *insns = get_insns ();
   6847  1.1  mrg   end_sequence ();
   6848  1.1  mrg   emit_insn (insns);
   6849  1.1  mrg 
   6850  1.1  mrg   return result;
   6851  1.1  mrg }
   6852  1.1  mrg 
   6853  1.1  mrg /* Inline expansion of a call to str(n)cmp and memcmp, with result going
   6854  1.1  mrg    to TARGET if that's convenient.
   6855  1.1  mrg    If the call is not been inlined, return NULL_RTX.  */
   6856  1.1  mrg 
   6857  1.1  mrg static rtx
   6858  1.1  mrg inline_expand_builtin_bytecmp (tree exp, rtx target)
   6859  1.1  mrg {
   6860  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   6861  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   6862  1.1  mrg   bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
   6863  1.1  mrg 
   6864  1.1  mrg   /* Do NOT apply this inlining expansion when optimizing for size or
   6865  1.1  mrg      optimization level below 2.  */
   6866  1.1  mrg   if (optimize < 2 || optimize_insn_for_size_p ())
   6867  1.1  mrg     return NULL_RTX;
   6868  1.1  mrg 
   6869  1.1  mrg   gcc_checking_assert (fcode == BUILT_IN_STRCMP
   6870  1.1  mrg 		       || fcode == BUILT_IN_STRNCMP
   6871  1.1  mrg 		       || fcode == BUILT_IN_MEMCMP);
   6872  1.1  mrg 
   6873  1.1  mrg   /* On a target where the type of the call (int) has same or narrower presicion
   6874  1.1  mrg      than unsigned char, give up the inlining expansion.  */
   6875  1.1  mrg   if (TYPE_PRECISION (unsigned_char_type_node)
   6876  1.1  mrg       >= TYPE_PRECISION (TREE_TYPE (exp)))
   6877  1.1  mrg     return NULL_RTX;
   6878  1.1  mrg 
   6879  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 0);
   6880  1.1  mrg   tree arg2 = CALL_EXPR_ARG (exp, 1);
   6881  1.1  mrg   tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
   6882  1.1  mrg 
   6883  1.1  mrg   unsigned HOST_WIDE_INT len1 = 0;
   6884  1.1  mrg   unsigned HOST_WIDE_INT len2 = 0;
   6885  1.1  mrg   unsigned HOST_WIDE_INT len3 = 0;
   6886  1.1  mrg 
   6887  1.1  mrg   /* Get the object representation of the initializers of ARG1 and ARG2
   6888  1.1  mrg      as strings, provided they refer to constant objects, with their byte
   6889  1.1  mrg      sizes in LEN1 and LEN2, respectively.  */
   6890  1.1  mrg   const char *bytes1 = getbyterep (arg1, &len1);
   6891  1.1  mrg   const char *bytes2 = getbyterep (arg2, &len2);
   6892  1.1  mrg 
   6893  1.1  mrg   /* Fail if neither argument refers to an initialized constant.  */
   6894  1.1  mrg   if (!bytes1 && !bytes2)
   6895  1.1  mrg     return NULL_RTX;
   6896  1.1  mrg 
   6897  1.1  mrg   if (is_ncmp)
   6898  1.1  mrg     {
   6899  1.1  mrg       /* Fail if the memcmp/strncmp bound is not a constant.  */
   6900  1.1  mrg       if (!tree_fits_uhwi_p (len3_tree))
   6901  1.1  mrg 	return NULL_RTX;
   6902  1.1  mrg 
   6903  1.1  mrg       len3 = tree_to_uhwi (len3_tree);
   6904  1.1  mrg 
   6905  1.1  mrg       if (fcode == BUILT_IN_MEMCMP)
   6906  1.1  mrg 	{
   6907  1.1  mrg 	  /* Fail if the memcmp bound is greater than the size of either
   6908  1.1  mrg 	     of the two constant objects.  */
   6909  1.1  mrg 	  if ((bytes1 && len1 < len3)
   6910  1.1  mrg 	      || (bytes2 && len2 < len3))
   6911  1.1  mrg 	    return NULL_RTX;
   6912  1.1  mrg 	}
   6913  1.1  mrg     }
   6914  1.1  mrg 
   6915  1.1  mrg   if (fcode != BUILT_IN_MEMCMP)
   6916  1.1  mrg     {
   6917  1.1  mrg       /* For string functions (i.e., strcmp and strncmp) reduce LEN1
   6918  1.1  mrg 	 and LEN2 to the length of the nul-terminated string stored
   6919  1.1  mrg 	 in each.  */
   6920  1.1  mrg       if (bytes1 != NULL)
   6921  1.1  mrg 	len1 = strnlen (bytes1, len1) + 1;
   6922  1.1  mrg       if (bytes2 != NULL)
   6923  1.1  mrg 	len2 = strnlen (bytes2, len2) + 1;
   6924  1.1  mrg     }
   6925  1.1  mrg 
   6926  1.1  mrg   /* See inline_string_cmp.  */
   6927  1.1  mrg   int const_str_n;
   6928  1.1  mrg   if (!len1)
   6929  1.1  mrg     const_str_n = 2;
   6930  1.1  mrg   else if (!len2)
   6931  1.1  mrg     const_str_n = 1;
   6932  1.1  mrg   else if (len2 > len1)
   6933  1.1  mrg     const_str_n = 1;
   6934  1.1  mrg   else
   6935  1.1  mrg     const_str_n = 2;
   6936  1.1  mrg 
   6937  1.1  mrg   /* For strncmp only, compute the new bound as the smallest of
   6938  1.1  mrg      the lengths of the two strings (plus 1) and the bound provided
   6939  1.1  mrg      to the function.  */
   6940  1.1  mrg   unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
   6941  1.1  mrg   if (is_ncmp && len3 < bound)
   6942  1.1  mrg     bound = len3;
   6943  1.1  mrg 
   6944  1.1  mrg   /* If the bound of the comparison is larger than the threshold,
   6945  1.1  mrg      do nothing.  */
   6946  1.1  mrg   if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
   6947  1.1  mrg     return NULL_RTX;
   6948  1.1  mrg 
   6949  1.1  mrg   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   6950  1.1  mrg 
   6951  1.1  mrg   /* Now, start inline expansion the call.  */
   6952  1.1  mrg   return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
   6953  1.1  mrg 			    (const_str_n == 1) ? bytes1 : bytes2, bound,
   6954  1.1  mrg 			    const_str_n, mode);
   6955  1.1  mrg }
   6956  1.1  mrg 
   6957  1.1  mrg /* Expand a call to __builtin_speculation_safe_value_<N>.  MODE
   6958  1.1  mrg    represents the size of the first argument to that call, or VOIDmode
   6959  1.1  mrg    if the argument is a pointer.  IGNORE will be true if the result
   6960  1.1  mrg    isn't used.  */
   6961  1.1  mrg static rtx
   6962  1.1  mrg expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
   6963  1.1  mrg 			       bool ignore)
   6964  1.1  mrg {
   6965  1.1  mrg   rtx val, failsafe;
   6966  1.1  mrg   unsigned nargs = call_expr_nargs (exp);
   6967  1.1  mrg 
   6968  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   6969  1.1  mrg 
   6970  1.1  mrg   if (mode == VOIDmode)
   6971  1.1  mrg     {
   6972  1.1  mrg       mode = TYPE_MODE (TREE_TYPE (arg0));
   6973  1.1  mrg       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
   6974  1.1  mrg     }
   6975  1.1  mrg 
   6976  1.1  mrg   val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
   6977  1.1  mrg 
   6978  1.1  mrg   /* An optional second argument can be used as a failsafe value on
   6979  1.1  mrg      some machines.  If it isn't present, then the failsafe value is
   6980  1.1  mrg      assumed to be 0.  */
   6981  1.1  mrg   if (nargs > 1)
   6982  1.1  mrg     {
   6983  1.1  mrg       tree arg1 = CALL_EXPR_ARG (exp, 1);
   6984  1.1  mrg       failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
   6985  1.1  mrg     }
   6986  1.1  mrg   else
   6987  1.1  mrg     failsafe = const0_rtx;
   6988  1.1  mrg 
   6989  1.1  mrg   /* If the result isn't used, the behavior is undefined.  It would be
   6990  1.1  mrg      nice to emit a warning here, but path splitting means this might
   6991  1.1  mrg      happen with legitimate code.  So simply drop the builtin
   6992  1.1  mrg      expansion in that case; we've handled any side-effects above.  */
   6993  1.1  mrg   if (ignore)
   6994  1.1  mrg     return const0_rtx;
   6995  1.1  mrg 
   6996  1.1  mrg   /* If we don't have a suitable target, create one to hold the result.  */
   6997  1.1  mrg   if (target == NULL || GET_MODE (target) != mode)
   6998  1.1  mrg     target = gen_reg_rtx (mode);
   6999  1.1  mrg 
   7000  1.1  mrg   if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
   7001  1.1  mrg     val = convert_modes (mode, VOIDmode, val, false);
   7002  1.1  mrg 
   7003  1.1  mrg   return targetm.speculation_safe_value (mode, target, val, failsafe);
   7004  1.1  mrg }
   7005  1.1  mrg 
   7006  1.1  mrg /* Expand an expression EXP that calls a built-in function,
   7007  1.1  mrg    with result going to TARGET if that's convenient
   7008  1.1  mrg    (and in mode MODE if that's convenient).
   7009  1.1  mrg    SUBTARGET may be used as the target for computing one of EXP's operands.
   7010  1.1  mrg    IGNORE is nonzero if the value is to be ignored.  */
   7011  1.1  mrg 
   7012  1.1  mrg rtx
   7013  1.1  mrg expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
   7014  1.1  mrg 		int ignore)
   7015  1.1  mrg {
   7016  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   7017  1.1  mrg   machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
   7018  1.1  mrg   int flags;
   7019  1.1  mrg 
   7020  1.1  mrg   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   7021  1.1  mrg     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
   7022  1.1  mrg 
   7023  1.1  mrg   /* When ASan is enabled, we don't want to expand some memory/string
   7024  1.1  mrg      builtins and rely on libsanitizer's hooks.  This allows us to avoid
   7025  1.1  mrg      redundant checks and be sure, that possible overflow will be detected
   7026  1.1  mrg      by ASan.  */
   7027  1.1  mrg 
   7028  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   7029  1.1  mrg   if ((flag_sanitize & SANITIZE_ADDRESS) && asan_intercepted_p (fcode))
   7030  1.1  mrg     return expand_call (exp, target, ignore);
   7031  1.1  mrg 
   7032  1.1  mrg   /* When not optimizing, generate calls to library functions for a certain
   7033  1.1  mrg      set of builtins.  */
   7034  1.1  mrg   if (!optimize
   7035  1.1  mrg       && !called_as_built_in (fndecl)
   7036  1.1  mrg       && fcode != BUILT_IN_FORK
   7037  1.1  mrg       && fcode != BUILT_IN_EXECL
   7038  1.1  mrg       && fcode != BUILT_IN_EXECV
   7039  1.1  mrg       && fcode != BUILT_IN_EXECLP
   7040  1.1  mrg       && fcode != BUILT_IN_EXECLE
   7041  1.1  mrg       && fcode != BUILT_IN_EXECVP
   7042  1.1  mrg       && fcode != BUILT_IN_EXECVE
   7043  1.1  mrg       && fcode != BUILT_IN_CLEAR_CACHE
   7044  1.1  mrg       && !ALLOCA_FUNCTION_CODE_P (fcode)
   7045  1.1  mrg       && fcode != BUILT_IN_FREE)
   7046  1.1  mrg     return expand_call (exp, target, ignore);
   7047  1.1  mrg 
   7048  1.1  mrg   /* The built-in function expanders test for target == const0_rtx
   7049  1.1  mrg      to determine whether the function's result will be ignored.  */
   7050  1.1  mrg   if (ignore)
   7051  1.1  mrg     target = const0_rtx;
   7052  1.1  mrg 
   7053  1.1  mrg   /* If the result of a pure or const built-in function is ignored, and
   7054  1.1  mrg      none of its arguments are volatile, we can avoid expanding the
   7055  1.1  mrg      built-in call and just evaluate the arguments for side-effects.  */
   7056  1.1  mrg   if (target == const0_rtx
   7057  1.1  mrg       && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
   7058  1.1  mrg       && !(flags & ECF_LOOPING_CONST_OR_PURE))
   7059  1.1  mrg     {
   7060  1.1  mrg       bool volatilep = false;
   7061  1.1  mrg       tree arg;
   7062  1.1  mrg       call_expr_arg_iterator iter;
   7063  1.1  mrg 
   7064  1.1  mrg       FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
   7065  1.1  mrg 	if (TREE_THIS_VOLATILE (arg))
   7066  1.1  mrg 	  {
   7067  1.1  mrg 	    volatilep = true;
   7068  1.1  mrg 	    break;
   7069  1.1  mrg 	  }
   7070  1.1  mrg 
   7071  1.1  mrg       if (! volatilep)
   7072  1.1  mrg 	{
   7073  1.1  mrg 	  FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
   7074  1.1  mrg 	    expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
   7075  1.1  mrg 	  return const0_rtx;
   7076  1.1  mrg 	}
   7077  1.1  mrg     }
   7078  1.1  mrg 
   7079  1.1  mrg   switch (fcode)
   7080  1.1  mrg     {
   7081  1.1  mrg     CASE_FLT_FN (BUILT_IN_FABS):
   7082  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   7083  1.1  mrg     case BUILT_IN_FABSD32:
   7084  1.1  mrg     case BUILT_IN_FABSD64:
   7085  1.1  mrg     case BUILT_IN_FABSD128:
   7086  1.1  mrg       target = expand_builtin_fabs (exp, target, subtarget);
   7087  1.1  mrg       if (target)
   7088  1.1  mrg 	return target;
   7089  1.1  mrg       break;
   7090  1.1  mrg 
   7091  1.1  mrg     CASE_FLT_FN (BUILT_IN_COPYSIGN):
   7092  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
   7093  1.1  mrg       target = expand_builtin_copysign (exp, target, subtarget);
   7094  1.1  mrg       if (target)
   7095  1.1  mrg 	return target;
   7096  1.1  mrg       break;
   7097  1.1  mrg 
   7098  1.1  mrg       /* Just do a normal library call if we were unable to fold
   7099  1.1  mrg 	 the values.  */
   7100  1.1  mrg     CASE_FLT_FN (BUILT_IN_CABS):
   7101  1.1  mrg       break;
   7102  1.1  mrg 
   7103  1.1  mrg     CASE_FLT_FN (BUILT_IN_FMA):
   7104  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
   7105  1.1  mrg       target = expand_builtin_mathfn_ternary (exp, target, subtarget);
   7106  1.1  mrg       if (target)
   7107  1.1  mrg 	return target;
   7108  1.1  mrg       break;
   7109  1.1  mrg 
   7110  1.1  mrg     CASE_FLT_FN (BUILT_IN_ILOGB):
   7111  1.1  mrg       if (! flag_unsafe_math_optimizations)
   7112  1.1  mrg 	break;
   7113  1.1  mrg       gcc_fallthrough ();
   7114  1.1  mrg     CASE_FLT_FN (BUILT_IN_ISINF):
   7115  1.1  mrg     CASE_FLT_FN (BUILT_IN_FINITE):
   7116  1.1  mrg     case BUILT_IN_ISFINITE:
   7117  1.1  mrg     case BUILT_IN_ISNORMAL:
   7118  1.1  mrg       target = expand_builtin_interclass_mathfn (exp, target);
   7119  1.1  mrg       if (target)
   7120  1.1  mrg 	return target;
   7121  1.1  mrg       break;
   7122  1.1  mrg 
   7123  1.1  mrg     CASE_FLT_FN (BUILT_IN_ICEIL):
   7124  1.1  mrg     CASE_FLT_FN (BUILT_IN_LCEIL):
   7125  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLCEIL):
   7126  1.1  mrg     CASE_FLT_FN (BUILT_IN_LFLOOR):
   7127  1.1  mrg     CASE_FLT_FN (BUILT_IN_IFLOOR):
   7128  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLFLOOR):
   7129  1.1  mrg       target = expand_builtin_int_roundingfn (exp, target);
   7130  1.1  mrg       if (target)
   7131  1.1  mrg 	return target;
   7132  1.1  mrg       break;
   7133  1.1  mrg 
   7134  1.1  mrg     CASE_FLT_FN (BUILT_IN_IRINT):
   7135  1.1  mrg     CASE_FLT_FN (BUILT_IN_LRINT):
   7136  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLRINT):
   7137  1.1  mrg     CASE_FLT_FN (BUILT_IN_IROUND):
   7138  1.1  mrg     CASE_FLT_FN (BUILT_IN_LROUND):
   7139  1.1  mrg     CASE_FLT_FN (BUILT_IN_LLROUND):
   7140  1.1  mrg       target = expand_builtin_int_roundingfn_2 (exp, target);
   7141  1.1  mrg       if (target)
   7142  1.1  mrg 	return target;
   7143  1.1  mrg       break;
   7144  1.1  mrg 
   7145  1.1  mrg     CASE_FLT_FN (BUILT_IN_POWI):
   7146  1.1  mrg       target = expand_builtin_powi (exp, target);
   7147  1.1  mrg       if (target)
   7148  1.1  mrg 	return target;
   7149  1.1  mrg       break;
   7150  1.1  mrg 
   7151  1.1  mrg     CASE_FLT_FN (BUILT_IN_CEXPI):
   7152  1.1  mrg       target = expand_builtin_cexpi (exp, target);
   7153  1.1  mrg       gcc_assert (target);
   7154  1.1  mrg       return target;
   7155  1.1  mrg 
   7156  1.1  mrg     CASE_FLT_FN (BUILT_IN_SIN):
   7157  1.1  mrg     CASE_FLT_FN (BUILT_IN_COS):
   7158  1.1  mrg       if (! flag_unsafe_math_optimizations)
   7159  1.1  mrg 	break;
   7160  1.1  mrg       target = expand_builtin_mathfn_3 (exp, target, subtarget);
   7161  1.1  mrg       if (target)
   7162  1.1  mrg 	return target;
   7163  1.1  mrg       break;
   7164  1.1  mrg 
   7165  1.1  mrg     CASE_FLT_FN (BUILT_IN_SINCOS):
   7166  1.1  mrg       if (! flag_unsafe_math_optimizations)
   7167  1.1  mrg 	break;
   7168  1.1  mrg       target = expand_builtin_sincos (exp);
   7169  1.1  mrg       if (target)
   7170  1.1  mrg 	return target;
   7171  1.1  mrg       break;
   7172  1.1  mrg 
   7173  1.1  mrg     case BUILT_IN_FEGETROUND:
   7174  1.1  mrg       target = expand_builtin_fegetround (exp, target, target_mode);
   7175  1.1  mrg       if (target)
   7176  1.1  mrg 	return target;
   7177  1.1  mrg       break;
   7178  1.1  mrg 
   7179  1.1  mrg     case BUILT_IN_FECLEAREXCEPT:
   7180  1.1  mrg       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
   7181  1.1  mrg 						      feclearexcept_optab);
   7182  1.1  mrg       if (target)
   7183  1.1  mrg 	return target;
   7184  1.1  mrg       break;
   7185  1.1  mrg 
   7186  1.1  mrg     case BUILT_IN_FERAISEEXCEPT:
   7187  1.1  mrg       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
   7188  1.1  mrg 						      feraiseexcept_optab);
   7189  1.1  mrg       if (target)
   7190  1.1  mrg 	return target;
   7191  1.1  mrg       break;
   7192  1.1  mrg 
   7193  1.1  mrg     case BUILT_IN_APPLY_ARGS:
   7194  1.1  mrg       return expand_builtin_apply_args ();
   7195  1.1  mrg 
   7196  1.1  mrg       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
   7197  1.1  mrg 	 FUNCTION with a copy of the parameters described by
   7198  1.1  mrg 	 ARGUMENTS, and ARGSIZE.  It returns a block of memory
   7199  1.1  mrg 	 allocated on the stack into which is stored all the registers
   7200  1.1  mrg 	 that might possibly be used for returning the result of a
   7201  1.1  mrg 	 function.  ARGUMENTS is the value returned by
   7202  1.1  mrg 	 __builtin_apply_args.  ARGSIZE is the number of bytes of
   7203  1.1  mrg 	 arguments that must be copied.  ??? How should this value be
   7204  1.1  mrg 	 computed?  We'll also need a safe worst case value for varargs
   7205  1.1  mrg 	 functions.  */
   7206  1.1  mrg     case BUILT_IN_APPLY:
   7207  1.1  mrg       if (!validate_arglist (exp, POINTER_TYPE,
   7208  1.1  mrg 			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
   7209  1.1  mrg 	  && !validate_arglist (exp, REFERENCE_TYPE,
   7210  1.1  mrg 				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   7211  1.1  mrg 	return const0_rtx;
   7212  1.1  mrg       else
   7213  1.1  mrg 	{
   7214  1.1  mrg 	  rtx ops[3];
   7215  1.1  mrg 
   7216  1.1  mrg 	  ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
   7217  1.1  mrg 	  ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
   7218  1.1  mrg 	  ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
   7219  1.1  mrg 
   7220  1.1  mrg 	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
   7221  1.1  mrg 	}
   7222  1.1  mrg 
   7223  1.1  mrg       /* __builtin_return (RESULT) causes the function to return the
   7224  1.1  mrg 	 value described by RESULT.  RESULT is address of the block of
   7225  1.1  mrg 	 memory returned by __builtin_apply.  */
   7226  1.1  mrg     case BUILT_IN_RETURN:
   7227  1.1  mrg       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   7228  1.1  mrg 	expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
   7229  1.1  mrg       return const0_rtx;
   7230  1.1  mrg 
   7231  1.1  mrg     case BUILT_IN_SAVEREGS:
   7232  1.1  mrg       return expand_builtin_saveregs ();
   7233  1.1  mrg 
   7234  1.1  mrg     case BUILT_IN_VA_ARG_PACK:
   7235  1.1  mrg       /* All valid uses of __builtin_va_arg_pack () are removed during
   7236  1.1  mrg 	 inlining.  */
   7237  1.1  mrg       error ("invalid use of %<__builtin_va_arg_pack ()%>");
   7238  1.1  mrg       return const0_rtx;
   7239  1.1  mrg 
   7240  1.1  mrg     case BUILT_IN_VA_ARG_PACK_LEN:
   7241  1.1  mrg       /* All valid uses of __builtin_va_arg_pack_len () are removed during
   7242  1.1  mrg 	 inlining.  */
   7243  1.1  mrg       error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
   7244  1.1  mrg       return const0_rtx;
   7245  1.1  mrg 
   7246  1.1  mrg       /* Return the address of the first anonymous stack arg.  */
   7247  1.1  mrg     case BUILT_IN_NEXT_ARG:
   7248  1.1  mrg       if (fold_builtin_next_arg (exp, false))
   7249  1.1  mrg 	return const0_rtx;
   7250  1.1  mrg       return expand_builtin_next_arg ();
   7251  1.1  mrg 
   7252  1.1  mrg     case BUILT_IN_CLEAR_CACHE:
   7253  1.1  mrg       expand_builtin___clear_cache (exp);
   7254  1.1  mrg       return const0_rtx;
   7255  1.1  mrg 
   7256  1.1  mrg     case BUILT_IN_CLASSIFY_TYPE:
   7257  1.1  mrg       return expand_builtin_classify_type (exp);
   7258  1.1  mrg 
   7259  1.1  mrg     case BUILT_IN_CONSTANT_P:
   7260  1.1  mrg       return const0_rtx;
   7261  1.1  mrg 
   7262  1.1  mrg     case BUILT_IN_FRAME_ADDRESS:
   7263  1.1  mrg     case BUILT_IN_RETURN_ADDRESS:
   7264  1.1  mrg       return expand_builtin_frame_address (fndecl, exp);
   7265  1.1  mrg 
   7266  1.1  mrg     /* Returns the address of the area where the structure is returned.
   7267  1.1  mrg        0 otherwise.  */
   7268  1.1  mrg     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
   7269  1.1  mrg       if (call_expr_nargs (exp) != 0
   7270  1.1  mrg 	  || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
   7271  1.1  mrg 	  || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
   7272  1.1  mrg 	return const0_rtx;
   7273  1.1  mrg       else
   7274  1.1  mrg 	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
   7275  1.1  mrg 
   7276  1.1  mrg     CASE_BUILT_IN_ALLOCA:
   7277  1.1  mrg       target = expand_builtin_alloca (exp);
   7278  1.1  mrg       if (target)
   7279  1.1  mrg 	return target;
   7280  1.1  mrg       break;
   7281  1.1  mrg 
   7282  1.1  mrg     case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
   7283  1.1  mrg       return expand_asan_emit_allocas_unpoison (exp);
   7284  1.1  mrg 
   7285  1.1  mrg     case BUILT_IN_STACK_SAVE:
   7286  1.1  mrg       return expand_stack_save ();
   7287  1.1  mrg 
   7288  1.1  mrg     case BUILT_IN_STACK_RESTORE:
   7289  1.1  mrg       expand_stack_restore (CALL_EXPR_ARG (exp, 0));
   7290  1.1  mrg       return const0_rtx;
   7291  1.1  mrg 
   7292  1.1  mrg     case BUILT_IN_BSWAP16:
   7293  1.1  mrg     case BUILT_IN_BSWAP32:
   7294  1.1  mrg     case BUILT_IN_BSWAP64:
   7295  1.1  mrg     case BUILT_IN_BSWAP128:
   7296  1.1  mrg       target = expand_builtin_bswap (target_mode, exp, target, subtarget);
   7297  1.1  mrg       if (target)
   7298  1.1  mrg 	return target;
   7299  1.1  mrg       break;
   7300  1.1  mrg 
   7301  1.1  mrg     CASE_INT_FN (BUILT_IN_FFS):
   7302  1.1  mrg       target = expand_builtin_unop (target_mode, exp, target,
   7303  1.1  mrg 				    subtarget, ffs_optab);
   7304  1.1  mrg       if (target)
   7305  1.1  mrg 	return target;
   7306  1.1  mrg       break;
   7307  1.1  mrg 
   7308  1.1  mrg     CASE_INT_FN (BUILT_IN_CLZ):
   7309  1.1  mrg       target = expand_builtin_unop (target_mode, exp, target,
   7310  1.1  mrg 				    subtarget, clz_optab);
   7311  1.1  mrg       if (target)
   7312  1.1  mrg 	return target;
   7313  1.1  mrg       break;
   7314  1.1  mrg 
   7315  1.1  mrg     CASE_INT_FN (BUILT_IN_CTZ):
   7316  1.1  mrg       target = expand_builtin_unop (target_mode, exp, target,
   7317  1.1  mrg 				    subtarget, ctz_optab);
   7318  1.1  mrg       if (target)
   7319  1.1  mrg 	return target;
   7320  1.1  mrg       break;
   7321  1.1  mrg 
   7322  1.1  mrg     CASE_INT_FN (BUILT_IN_CLRSB):
   7323  1.1  mrg       target = expand_builtin_unop (target_mode, exp, target,
   7324  1.1  mrg 				    subtarget, clrsb_optab);
   7325  1.1  mrg       if (target)
   7326  1.1  mrg 	return target;
   7327  1.1  mrg       break;
   7328  1.1  mrg 
   7329  1.1  mrg     CASE_INT_FN (BUILT_IN_POPCOUNT):
   7330  1.1  mrg       target = expand_builtin_unop (target_mode, exp, target,
   7331  1.1  mrg 				    subtarget, popcount_optab);
   7332  1.1  mrg       if (target)
   7333  1.1  mrg 	return target;
   7334  1.1  mrg       break;
   7335  1.1  mrg 
   7336  1.1  mrg     CASE_INT_FN (BUILT_IN_PARITY):
   7337  1.1  mrg       target = expand_builtin_unop (target_mode, exp, target,
   7338  1.1  mrg 				    subtarget, parity_optab);
   7339  1.1  mrg       if (target)
   7340  1.1  mrg 	return target;
   7341  1.1  mrg       break;
   7342  1.1  mrg 
   7343  1.1  mrg     case BUILT_IN_STRLEN:
   7344  1.1  mrg       target = expand_builtin_strlen (exp, target, target_mode);
   7345  1.1  mrg       if (target)
   7346  1.1  mrg 	return target;
   7347  1.1  mrg       break;
   7348  1.1  mrg 
   7349  1.1  mrg     case BUILT_IN_STRNLEN:
   7350  1.1  mrg       target = expand_builtin_strnlen (exp, target, target_mode);
   7351  1.1  mrg       if (target)
   7352  1.1  mrg 	return target;
   7353  1.1  mrg       break;
   7354  1.1  mrg 
   7355  1.1  mrg     case BUILT_IN_STRCPY:
   7356  1.1  mrg       target = expand_builtin_strcpy (exp, target);
   7357  1.1  mrg       if (target)
   7358  1.1  mrg 	return target;
   7359  1.1  mrg       break;
   7360  1.1  mrg 
   7361  1.1  mrg     case BUILT_IN_STRNCPY:
   7362  1.1  mrg       target = expand_builtin_strncpy (exp, target);
   7363  1.1  mrg       if (target)
   7364  1.1  mrg 	return target;
   7365  1.1  mrg       break;
   7366  1.1  mrg 
   7367  1.1  mrg     case BUILT_IN_STPCPY:
   7368  1.1  mrg       target = expand_builtin_stpcpy (exp, target, mode);
   7369  1.1  mrg       if (target)
   7370  1.1  mrg 	return target;
   7371  1.1  mrg       break;
   7372  1.1  mrg 
   7373  1.1  mrg     case BUILT_IN_MEMCPY:
   7374  1.1  mrg       target = expand_builtin_memcpy (exp, target);
   7375  1.1  mrg       if (target)
   7376  1.1  mrg 	return target;
   7377  1.1  mrg       break;
   7378  1.1  mrg 
   7379  1.1  mrg     case BUILT_IN_MEMMOVE:
   7380  1.1  mrg       target = expand_builtin_memmove (exp, target);
   7381  1.1  mrg       if (target)
   7382  1.1  mrg 	return target;
   7383  1.1  mrg       break;
   7384  1.1  mrg 
   7385  1.1  mrg     case BUILT_IN_MEMPCPY:
   7386  1.1  mrg       target = expand_builtin_mempcpy (exp, target);
   7387  1.1  mrg       if (target)
   7388  1.1  mrg 	return target;
   7389  1.1  mrg       break;
   7390  1.1  mrg 
   7391  1.1  mrg     case BUILT_IN_MEMSET:
   7392  1.1  mrg       target = expand_builtin_memset (exp, target, mode);
   7393  1.1  mrg       if (target)
   7394  1.1  mrg 	return target;
   7395  1.1  mrg       break;
   7396  1.1  mrg 
   7397  1.1  mrg     case BUILT_IN_BZERO:
   7398  1.1  mrg       target = expand_builtin_bzero (exp);
   7399  1.1  mrg       if (target)
   7400  1.1  mrg 	return target;
   7401  1.1  mrg       break;
   7402  1.1  mrg 
   7403  1.1  mrg     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
   7404  1.1  mrg        back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
   7405  1.1  mrg        when changing it to a strcmp call.  */
   7406  1.1  mrg     case BUILT_IN_STRCMP_EQ:
   7407  1.1  mrg       target = expand_builtin_memcmp (exp, target, true);
   7408  1.1  mrg       if (target)
   7409  1.1  mrg 	return target;
   7410  1.1  mrg 
   7411  1.1  mrg       /* Change this call back to a BUILT_IN_STRCMP.  */
   7412  1.1  mrg       TREE_OPERAND (exp, 1)
   7413  1.1  mrg 	= build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
   7414  1.1  mrg 
   7415  1.1  mrg       /* Delete the last parameter.  */
   7416  1.1  mrg       unsigned int i;
   7417  1.1  mrg       vec<tree, va_gc> *arg_vec;
   7418  1.1  mrg       vec_alloc (arg_vec, 2);
   7419  1.1  mrg       for (i = 0; i < 2; i++)
   7420  1.1  mrg 	arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
   7421  1.1  mrg       exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
   7422  1.1  mrg       /* FALLTHROUGH */
   7423  1.1  mrg 
   7424  1.1  mrg     case BUILT_IN_STRCMP:
   7425  1.1  mrg       target = expand_builtin_strcmp (exp, target);
   7426  1.1  mrg       if (target)
   7427  1.1  mrg 	return target;
   7428  1.1  mrg       break;
   7429  1.1  mrg 
   7430  1.1  mrg     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
   7431  1.1  mrg        back to a BUILT_IN_STRNCMP.  */
   7432  1.1  mrg     case BUILT_IN_STRNCMP_EQ:
   7433  1.1  mrg       target = expand_builtin_memcmp (exp, target, true);
   7434  1.1  mrg       if (target)
   7435  1.1  mrg 	return target;
   7436  1.1  mrg 
   7437  1.1  mrg       /* Change it back to a BUILT_IN_STRNCMP.  */
   7438  1.1  mrg       TREE_OPERAND (exp, 1)
   7439  1.1  mrg 	= build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
   7440  1.1  mrg       /* FALLTHROUGH */
   7441  1.1  mrg 
   7442  1.1  mrg     case BUILT_IN_STRNCMP:
   7443  1.1  mrg       target = expand_builtin_strncmp (exp, target, mode);
   7444  1.1  mrg       if (target)
   7445  1.1  mrg 	return target;
   7446  1.1  mrg       break;
   7447  1.1  mrg 
   7448  1.1  mrg     case BUILT_IN_BCMP:
   7449  1.1  mrg     case BUILT_IN_MEMCMP:
   7450  1.1  mrg     case BUILT_IN_MEMCMP_EQ:
   7451  1.1  mrg       target = expand_builtin_memcmp (exp, target, fcode == BUILT_IN_MEMCMP_EQ);
   7452  1.1  mrg       if (target)
   7453  1.1  mrg 	return target;
   7454  1.1  mrg       if (fcode == BUILT_IN_MEMCMP_EQ)
   7455  1.1  mrg 	{
   7456  1.1  mrg 	  tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
   7457  1.1  mrg 	  TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
   7458  1.1  mrg 	}
   7459  1.1  mrg       break;
   7460  1.1  mrg 
   7461  1.1  mrg     case BUILT_IN_SETJMP:
   7462  1.1  mrg       /* This should have been lowered to the builtins below.  */
   7463  1.1  mrg       gcc_unreachable ();
   7464  1.1  mrg 
   7465  1.1  mrg     case BUILT_IN_SETJMP_SETUP:
   7466  1.1  mrg       /* __builtin_setjmp_setup is passed a pointer to an array of five words
   7467  1.1  mrg           and the receiver label.  */
   7468  1.1  mrg       if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
   7469  1.1  mrg 	{
   7470  1.1  mrg 	  rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
   7471  1.1  mrg 				      VOIDmode, EXPAND_NORMAL);
   7472  1.1  mrg 	  tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
   7473  1.1  mrg 	  rtx_insn *label_r = label_rtx (label);
   7474  1.1  mrg 
   7475  1.1  mrg 	  /* This is copied from the handling of non-local gotos.  */
   7476  1.1  mrg 	  expand_builtin_setjmp_setup (buf_addr, label_r);
   7477  1.1  mrg 	  nonlocal_goto_handler_labels
   7478  1.1  mrg 	    = gen_rtx_INSN_LIST (VOIDmode, label_r,
   7479  1.1  mrg 				 nonlocal_goto_handler_labels);
   7480  1.1  mrg 	  /* ??? Do not let expand_label treat us as such since we would
   7481  1.1  mrg 	     not want to be both on the list of non-local labels and on
   7482  1.1  mrg 	     the list of forced labels.  */
   7483  1.1  mrg 	  FORCED_LABEL (label) = 0;
   7484  1.1  mrg 	  return const0_rtx;
   7485  1.1  mrg 	}
   7486  1.1  mrg       break;
   7487  1.1  mrg 
   7488  1.1  mrg     case BUILT_IN_SETJMP_RECEIVER:
   7489  1.1  mrg        /* __builtin_setjmp_receiver is passed the receiver label.  */
   7490  1.1  mrg       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   7491  1.1  mrg 	{
   7492  1.1  mrg 	  tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
   7493  1.1  mrg 	  rtx_insn *label_r = label_rtx (label);
   7494  1.1  mrg 
   7495  1.1  mrg 	  expand_builtin_setjmp_receiver (label_r);
   7496  1.1  mrg 	  return const0_rtx;
   7497  1.1  mrg 	}
   7498  1.1  mrg       break;
   7499  1.1  mrg 
   7500  1.1  mrg       /* __builtin_longjmp is passed a pointer to an array of five words.
   7501  1.1  mrg 	 It's similar to the C library longjmp function but works with
   7502  1.1  mrg 	 __builtin_setjmp above.  */
   7503  1.1  mrg     case BUILT_IN_LONGJMP:
   7504  1.1  mrg       if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   7505  1.1  mrg 	{
   7506  1.1  mrg 	  rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
   7507  1.1  mrg 				      VOIDmode, EXPAND_NORMAL);
   7508  1.1  mrg 	  rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
   7509  1.1  mrg 
   7510  1.1  mrg 	  if (value != const1_rtx)
   7511  1.1  mrg 	    {
   7512  1.1  mrg 	      error ("%<__builtin_longjmp%> second argument must be 1");
   7513  1.1  mrg 	      return const0_rtx;
   7514  1.1  mrg 	    }
   7515  1.1  mrg 
   7516  1.1  mrg 	  expand_builtin_longjmp (buf_addr, value);
   7517  1.1  mrg 	  return const0_rtx;
   7518  1.1  mrg 	}
   7519  1.1  mrg       break;
   7520  1.1  mrg 
   7521  1.1  mrg     case BUILT_IN_NONLOCAL_GOTO:
   7522  1.1  mrg       target = expand_builtin_nonlocal_goto (exp);
   7523  1.1  mrg       if (target)
   7524  1.1  mrg 	return target;
   7525  1.1  mrg       break;
   7526  1.1  mrg 
   7527  1.1  mrg       /* This updates the setjmp buffer that is its argument with the value
   7528  1.1  mrg 	 of the current stack pointer.  */
   7529  1.1  mrg     case BUILT_IN_UPDATE_SETJMP_BUF:
   7530  1.1  mrg       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
   7531  1.1  mrg 	{
   7532  1.1  mrg 	  rtx buf_addr
   7533  1.1  mrg 	    = expand_normal (CALL_EXPR_ARG (exp, 0));
   7534  1.1  mrg 
   7535  1.1  mrg 	  expand_builtin_update_setjmp_buf (buf_addr);
   7536  1.1  mrg 	  return const0_rtx;
   7537  1.1  mrg 	}
   7538  1.1  mrg       break;
   7539  1.1  mrg 
   7540  1.1  mrg     case BUILT_IN_TRAP:
   7541  1.1  mrg       expand_builtin_trap ();
   7542  1.1  mrg       return const0_rtx;
   7543  1.1  mrg 
   7544  1.1  mrg     case BUILT_IN_UNREACHABLE:
   7545  1.1  mrg       expand_builtin_unreachable ();
   7546  1.1  mrg       return const0_rtx;
   7547  1.1  mrg 
   7548  1.1  mrg     CASE_FLT_FN (BUILT_IN_SIGNBIT):
   7549  1.1  mrg     case BUILT_IN_SIGNBITD32:
   7550  1.1  mrg     case BUILT_IN_SIGNBITD64:
   7551  1.1  mrg     case BUILT_IN_SIGNBITD128:
   7552  1.1  mrg       target = expand_builtin_signbit (exp, target);
   7553  1.1  mrg       if (target)
   7554  1.1  mrg 	return target;
   7555  1.1  mrg       break;
   7556  1.1  mrg 
   7557  1.1  mrg       /* Various hooks for the DWARF 2 __throw routine.  */
   7558  1.1  mrg     case BUILT_IN_UNWIND_INIT:
   7559  1.1  mrg       expand_builtin_unwind_init ();
   7560  1.1  mrg       return const0_rtx;
   7561  1.1  mrg     case BUILT_IN_DWARF_CFA:
   7562  1.1  mrg       return virtual_cfa_rtx;
   7563  1.1  mrg #ifdef DWARF2_UNWIND_INFO
   7564  1.1  mrg     case BUILT_IN_DWARF_SP_COLUMN:
   7565  1.1  mrg       return expand_builtin_dwarf_sp_column ();
   7566  1.1  mrg     case BUILT_IN_INIT_DWARF_REG_SIZES:
   7567  1.1  mrg       expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
   7568  1.1  mrg       return const0_rtx;
   7569  1.1  mrg #endif
   7570  1.1  mrg     case BUILT_IN_FROB_RETURN_ADDR:
   7571  1.1  mrg       return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
   7572  1.1  mrg     case BUILT_IN_EXTRACT_RETURN_ADDR:
   7573  1.1  mrg       return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
   7574  1.1  mrg     case BUILT_IN_EH_RETURN:
   7575  1.1  mrg       expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
   7576  1.1  mrg 				CALL_EXPR_ARG (exp, 1));
   7577  1.1  mrg       return const0_rtx;
   7578  1.1  mrg     case BUILT_IN_EH_RETURN_DATA_REGNO:
   7579  1.1  mrg       return expand_builtin_eh_return_data_regno (exp);
   7580  1.1  mrg     case BUILT_IN_EXTEND_POINTER:
   7581  1.1  mrg       return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
   7582  1.1  mrg     case BUILT_IN_EH_POINTER:
   7583  1.1  mrg       return expand_builtin_eh_pointer (exp);
   7584  1.1  mrg     case BUILT_IN_EH_FILTER:
   7585  1.1  mrg       return expand_builtin_eh_filter (exp);
   7586  1.1  mrg     case BUILT_IN_EH_COPY_VALUES:
   7587  1.1  mrg       return expand_builtin_eh_copy_values (exp);
   7588  1.1  mrg 
   7589  1.1  mrg     case BUILT_IN_VA_START:
   7590  1.1  mrg       return expand_builtin_va_start (exp);
   7591  1.1  mrg     case BUILT_IN_VA_END:
   7592  1.1  mrg       return expand_builtin_va_end (exp);
   7593  1.1  mrg     case BUILT_IN_VA_COPY:
   7594  1.1  mrg       return expand_builtin_va_copy (exp);
   7595  1.1  mrg     case BUILT_IN_EXPECT:
   7596  1.1  mrg       return expand_builtin_expect (exp, target);
   7597  1.1  mrg     case BUILT_IN_EXPECT_WITH_PROBABILITY:
   7598  1.1  mrg       return expand_builtin_expect_with_probability (exp, target);
   7599  1.1  mrg     case BUILT_IN_ASSUME_ALIGNED:
   7600  1.1  mrg       return expand_builtin_assume_aligned (exp, target);
   7601  1.1  mrg     case BUILT_IN_PREFETCH:
   7602  1.1  mrg       expand_builtin_prefetch (exp);
   7603  1.1  mrg       return const0_rtx;
   7604  1.1  mrg 
   7605  1.1  mrg     case BUILT_IN_INIT_TRAMPOLINE:
   7606  1.1  mrg       return expand_builtin_init_trampoline (exp, true);
   7607  1.1  mrg     case BUILT_IN_INIT_HEAP_TRAMPOLINE:
   7608  1.1  mrg       return expand_builtin_init_trampoline (exp, false);
   7609  1.1  mrg     case BUILT_IN_ADJUST_TRAMPOLINE:
   7610  1.1  mrg       return expand_builtin_adjust_trampoline (exp);
   7611  1.1  mrg 
   7612  1.1  mrg     case BUILT_IN_INIT_DESCRIPTOR:
   7613  1.1  mrg       return expand_builtin_init_descriptor (exp);
   7614  1.1  mrg     case BUILT_IN_ADJUST_DESCRIPTOR:
   7615  1.1  mrg       return expand_builtin_adjust_descriptor (exp);
   7616  1.1  mrg 
   7617  1.1  mrg     case BUILT_IN_FORK:
   7618  1.1  mrg     case BUILT_IN_EXECL:
   7619  1.1  mrg     case BUILT_IN_EXECV:
   7620  1.1  mrg     case BUILT_IN_EXECLP:
   7621  1.1  mrg     case BUILT_IN_EXECLE:
   7622  1.1  mrg     case BUILT_IN_EXECVP:
   7623  1.1  mrg     case BUILT_IN_EXECVE:
   7624  1.1  mrg       target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
   7625  1.1  mrg       if (target)
   7626  1.1  mrg 	return target;
   7627  1.1  mrg       break;
   7628  1.1  mrg 
   7629  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_ADD_1:
   7630  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_ADD_2:
   7631  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_ADD_4:
   7632  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_ADD_8:
   7633  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_ADD_16:
   7634  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
   7635  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
   7636  1.1  mrg       if (target)
   7637  1.1  mrg 	return target;
   7638  1.1  mrg       break;
   7639  1.1  mrg 
   7640  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_SUB_1:
   7641  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_SUB_2:
   7642  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_SUB_4:
   7643  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_SUB_8:
   7644  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_SUB_16:
   7645  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
   7646  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
   7647  1.1  mrg       if (target)
   7648  1.1  mrg 	return target;
   7649  1.1  mrg       break;
   7650  1.1  mrg 
   7651  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_OR_1:
   7652  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_OR_2:
   7653  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_OR_4:
   7654  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_OR_8:
   7655  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_OR_16:
   7656  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
   7657  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
   7658  1.1  mrg       if (target)
   7659  1.1  mrg 	return target;
   7660  1.1  mrg       break;
   7661  1.1  mrg 
   7662  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_AND_1:
   7663  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_AND_2:
   7664  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_AND_4:
   7665  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_AND_8:
   7666  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_AND_16:
   7667  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
   7668  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, AND, false, target);
   7669  1.1  mrg       if (target)
   7670  1.1  mrg 	return target;
   7671  1.1  mrg       break;
   7672  1.1  mrg 
   7673  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_XOR_1:
   7674  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_XOR_2:
   7675  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_XOR_4:
   7676  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_XOR_8:
   7677  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_XOR_16:
   7678  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
   7679  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
   7680  1.1  mrg       if (target)
   7681  1.1  mrg 	return target;
   7682  1.1  mrg       break;
   7683  1.1  mrg 
   7684  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_NAND_1:
   7685  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_NAND_2:
   7686  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_NAND_4:
   7687  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_NAND_8:
   7688  1.1  mrg     case BUILT_IN_SYNC_FETCH_AND_NAND_16:
   7689  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
   7690  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
   7691  1.1  mrg       if (target)
   7692  1.1  mrg 	return target;
   7693  1.1  mrg       break;
   7694  1.1  mrg 
   7695  1.1  mrg     case BUILT_IN_SYNC_ADD_AND_FETCH_1:
   7696  1.1  mrg     case BUILT_IN_SYNC_ADD_AND_FETCH_2:
   7697  1.1  mrg     case BUILT_IN_SYNC_ADD_AND_FETCH_4:
   7698  1.1  mrg     case BUILT_IN_SYNC_ADD_AND_FETCH_8:
   7699  1.1  mrg     case BUILT_IN_SYNC_ADD_AND_FETCH_16:
   7700  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
   7701  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
   7702  1.1  mrg       if (target)
   7703  1.1  mrg 	return target;
   7704  1.1  mrg       break;
   7705  1.1  mrg 
   7706  1.1  mrg     case BUILT_IN_SYNC_SUB_AND_FETCH_1:
   7707  1.1  mrg     case BUILT_IN_SYNC_SUB_AND_FETCH_2:
   7708  1.1  mrg     case BUILT_IN_SYNC_SUB_AND_FETCH_4:
   7709  1.1  mrg     case BUILT_IN_SYNC_SUB_AND_FETCH_8:
   7710  1.1  mrg     case BUILT_IN_SYNC_SUB_AND_FETCH_16:
   7711  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
   7712  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
   7713  1.1  mrg       if (target)
   7714  1.1  mrg 	return target;
   7715  1.1  mrg       break;
   7716  1.1  mrg 
   7717  1.1  mrg     case BUILT_IN_SYNC_OR_AND_FETCH_1:
   7718  1.1  mrg     case BUILT_IN_SYNC_OR_AND_FETCH_2:
   7719  1.1  mrg     case BUILT_IN_SYNC_OR_AND_FETCH_4:
   7720  1.1  mrg     case BUILT_IN_SYNC_OR_AND_FETCH_8:
   7721  1.1  mrg     case BUILT_IN_SYNC_OR_AND_FETCH_16:
   7722  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
   7723  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
   7724  1.1  mrg       if (target)
   7725  1.1  mrg 	return target;
   7726  1.1  mrg       break;
   7727  1.1  mrg 
   7728  1.1  mrg     case BUILT_IN_SYNC_AND_AND_FETCH_1:
   7729  1.1  mrg     case BUILT_IN_SYNC_AND_AND_FETCH_2:
   7730  1.1  mrg     case BUILT_IN_SYNC_AND_AND_FETCH_4:
   7731  1.1  mrg     case BUILT_IN_SYNC_AND_AND_FETCH_8:
   7732  1.1  mrg     case BUILT_IN_SYNC_AND_AND_FETCH_16:
   7733  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
   7734  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, AND, true, target);
   7735  1.1  mrg       if (target)
   7736  1.1  mrg 	return target;
   7737  1.1  mrg       break;
   7738  1.1  mrg 
   7739  1.1  mrg     case BUILT_IN_SYNC_XOR_AND_FETCH_1:
   7740  1.1  mrg     case BUILT_IN_SYNC_XOR_AND_FETCH_2:
   7741  1.1  mrg     case BUILT_IN_SYNC_XOR_AND_FETCH_4:
   7742  1.1  mrg     case BUILT_IN_SYNC_XOR_AND_FETCH_8:
   7743  1.1  mrg     case BUILT_IN_SYNC_XOR_AND_FETCH_16:
   7744  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
   7745  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
   7746  1.1  mrg       if (target)
   7747  1.1  mrg 	return target;
   7748  1.1  mrg       break;
   7749  1.1  mrg 
   7750  1.1  mrg     case BUILT_IN_SYNC_NAND_AND_FETCH_1:
   7751  1.1  mrg     case BUILT_IN_SYNC_NAND_AND_FETCH_2:
   7752  1.1  mrg     case BUILT_IN_SYNC_NAND_AND_FETCH_4:
   7753  1.1  mrg     case BUILT_IN_SYNC_NAND_AND_FETCH_8:
   7754  1.1  mrg     case BUILT_IN_SYNC_NAND_AND_FETCH_16:
   7755  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
   7756  1.1  mrg       target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
   7757  1.1  mrg       if (target)
   7758  1.1  mrg 	return target;
   7759  1.1  mrg       break;
   7760  1.1  mrg 
   7761  1.1  mrg     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
   7762  1.1  mrg     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
   7763  1.1  mrg     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
   7764  1.1  mrg     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
   7765  1.1  mrg     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
   7766  1.1  mrg       if (mode == VOIDmode)
   7767  1.1  mrg 	mode = TYPE_MODE (boolean_type_node);
   7768  1.1  mrg       if (!target || !register_operand (target, mode))
   7769  1.1  mrg 	target = gen_reg_rtx (mode);
   7770  1.1  mrg 
   7771  1.1  mrg       mode = get_builtin_sync_mode
   7772  1.1  mrg 				(fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
   7773  1.1  mrg       target = expand_builtin_compare_and_swap (mode, exp, true, target);
   7774  1.1  mrg       if (target)
   7775  1.1  mrg 	return target;
   7776  1.1  mrg       break;
   7777  1.1  mrg 
   7778  1.1  mrg     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
   7779  1.1  mrg     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
   7780  1.1  mrg     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
   7781  1.1  mrg     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
   7782  1.1  mrg     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
   7783  1.1  mrg       mode = get_builtin_sync_mode
   7784  1.1  mrg 				(fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
   7785  1.1  mrg       target = expand_builtin_compare_and_swap (mode, exp, false, target);
   7786  1.1  mrg       if (target)
   7787  1.1  mrg 	return target;
   7788  1.1  mrg       break;
   7789  1.1  mrg 
   7790  1.1  mrg     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
   7791  1.1  mrg     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
   7792  1.1  mrg     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
   7793  1.1  mrg     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
   7794  1.1  mrg     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
   7795  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
   7796  1.1  mrg       target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
   7797  1.1  mrg       if (target)
   7798  1.1  mrg 	return target;
   7799  1.1  mrg       break;
   7800  1.1  mrg 
   7801  1.1  mrg     case BUILT_IN_SYNC_LOCK_RELEASE_1:
   7802  1.1  mrg     case BUILT_IN_SYNC_LOCK_RELEASE_2:
   7803  1.1  mrg     case BUILT_IN_SYNC_LOCK_RELEASE_4:
   7804  1.1  mrg     case BUILT_IN_SYNC_LOCK_RELEASE_8:
   7805  1.1  mrg     case BUILT_IN_SYNC_LOCK_RELEASE_16:
   7806  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
   7807  1.1  mrg       expand_builtin_sync_lock_release (mode, exp);
   7808  1.1  mrg       return const0_rtx;
   7809  1.1  mrg 
   7810  1.1  mrg     case BUILT_IN_SYNC_SYNCHRONIZE:
   7811  1.1  mrg       expand_builtin_sync_synchronize ();
   7812  1.1  mrg       return const0_rtx;
   7813  1.1  mrg 
   7814  1.1  mrg     case BUILT_IN_ATOMIC_EXCHANGE_1:
   7815  1.1  mrg     case BUILT_IN_ATOMIC_EXCHANGE_2:
   7816  1.1  mrg     case BUILT_IN_ATOMIC_EXCHANGE_4:
   7817  1.1  mrg     case BUILT_IN_ATOMIC_EXCHANGE_8:
   7818  1.1  mrg     case BUILT_IN_ATOMIC_EXCHANGE_16:
   7819  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
   7820  1.1  mrg       target = expand_builtin_atomic_exchange (mode, exp, target);
   7821  1.1  mrg       if (target)
   7822  1.1  mrg 	return target;
   7823  1.1  mrg       break;
   7824  1.1  mrg 
   7825  1.1  mrg     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
   7826  1.1  mrg     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
   7827  1.1  mrg     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
   7828  1.1  mrg     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
   7829  1.1  mrg     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
   7830  1.1  mrg       {
   7831  1.1  mrg 	unsigned int nargs, z;
   7832  1.1  mrg 	vec<tree, va_gc> *vec;
   7833  1.1  mrg 
   7834  1.1  mrg 	mode =
   7835  1.1  mrg 	    get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
   7836  1.1  mrg 	target = expand_builtin_atomic_compare_exchange (mode, exp, target);
   7837  1.1  mrg 	if (target)
   7838  1.1  mrg 	  return target;
   7839  1.1  mrg 
   7840  1.1  mrg 	/* If this is turned into an external library call, the weak parameter
   7841  1.1  mrg 	   must be dropped to match the expected parameter list.  */
   7842  1.1  mrg 	nargs = call_expr_nargs (exp);
   7843  1.1  mrg 	vec_alloc (vec, nargs - 1);
   7844  1.1  mrg 	for (z = 0; z < 3; z++)
   7845  1.1  mrg 	  vec->quick_push (CALL_EXPR_ARG (exp, z));
   7846  1.1  mrg 	/* Skip the boolean weak parameter.  */
   7847  1.1  mrg 	for (z = 4; z < 6; z++)
   7848  1.1  mrg 	  vec->quick_push (CALL_EXPR_ARG (exp, z));
   7849  1.1  mrg 	exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
   7850  1.1  mrg 	break;
   7851  1.1  mrg       }
   7852  1.1  mrg 
   7853  1.1  mrg     case BUILT_IN_ATOMIC_LOAD_1:
   7854  1.1  mrg     case BUILT_IN_ATOMIC_LOAD_2:
   7855  1.1  mrg     case BUILT_IN_ATOMIC_LOAD_4:
   7856  1.1  mrg     case BUILT_IN_ATOMIC_LOAD_8:
   7857  1.1  mrg     case BUILT_IN_ATOMIC_LOAD_16:
   7858  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
   7859  1.1  mrg       target = expand_builtin_atomic_load (mode, exp, target);
   7860  1.1  mrg       if (target)
   7861  1.1  mrg 	return target;
   7862  1.1  mrg       break;
   7863  1.1  mrg 
   7864  1.1  mrg     case BUILT_IN_ATOMIC_STORE_1:
   7865  1.1  mrg     case BUILT_IN_ATOMIC_STORE_2:
   7866  1.1  mrg     case BUILT_IN_ATOMIC_STORE_4:
   7867  1.1  mrg     case BUILT_IN_ATOMIC_STORE_8:
   7868  1.1  mrg     case BUILT_IN_ATOMIC_STORE_16:
   7869  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
   7870  1.1  mrg       target = expand_builtin_atomic_store (mode, exp);
   7871  1.1  mrg       if (target)
   7872  1.1  mrg 	return const0_rtx;
   7873  1.1  mrg       break;
   7874  1.1  mrg 
   7875  1.1  mrg     case BUILT_IN_ATOMIC_ADD_FETCH_1:
   7876  1.1  mrg     case BUILT_IN_ATOMIC_ADD_FETCH_2:
   7877  1.1  mrg     case BUILT_IN_ATOMIC_ADD_FETCH_4:
   7878  1.1  mrg     case BUILT_IN_ATOMIC_ADD_FETCH_8:
   7879  1.1  mrg     case BUILT_IN_ATOMIC_ADD_FETCH_16:
   7880  1.1  mrg       {
   7881  1.1  mrg 	enum built_in_function lib;
   7882  1.1  mrg 	mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
   7883  1.1  mrg 	lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
   7884  1.1  mrg 				       (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
   7885  1.1  mrg 	target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
   7886  1.1  mrg 						 ignore, lib);
   7887  1.1  mrg 	if (target)
   7888  1.1  mrg 	  return target;
   7889  1.1  mrg 	break;
   7890  1.1  mrg       }
   7891  1.1  mrg     case BUILT_IN_ATOMIC_SUB_FETCH_1:
   7892  1.1  mrg     case BUILT_IN_ATOMIC_SUB_FETCH_2:
   7893  1.1  mrg     case BUILT_IN_ATOMIC_SUB_FETCH_4:
   7894  1.1  mrg     case BUILT_IN_ATOMIC_SUB_FETCH_8:
   7895  1.1  mrg     case BUILT_IN_ATOMIC_SUB_FETCH_16:
   7896  1.1  mrg       {
   7897  1.1  mrg 	enum built_in_function lib;
   7898  1.1  mrg 	mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
   7899  1.1  mrg 	lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
   7900  1.1  mrg 				       (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
   7901  1.1  mrg 	target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
   7902  1.1  mrg 						 ignore, lib);
   7903  1.1  mrg 	if (target)
   7904  1.1  mrg 	  return target;
   7905  1.1  mrg 	break;
   7906  1.1  mrg       }
   7907  1.1  mrg     case BUILT_IN_ATOMIC_AND_FETCH_1:
   7908  1.1  mrg     case BUILT_IN_ATOMIC_AND_FETCH_2:
   7909  1.1  mrg     case BUILT_IN_ATOMIC_AND_FETCH_4:
   7910  1.1  mrg     case BUILT_IN_ATOMIC_AND_FETCH_8:
   7911  1.1  mrg     case BUILT_IN_ATOMIC_AND_FETCH_16:
   7912  1.1  mrg       {
   7913  1.1  mrg 	enum built_in_function lib;
   7914  1.1  mrg 	mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
   7915  1.1  mrg 	lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
   7916  1.1  mrg 				       (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
   7917  1.1  mrg 	target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
   7918  1.1  mrg 						 ignore, lib);
   7919  1.1  mrg 	if (target)
   7920  1.1  mrg 	  return target;
   7921  1.1  mrg 	break;
   7922  1.1  mrg       }
   7923  1.1  mrg     case BUILT_IN_ATOMIC_NAND_FETCH_1:
   7924  1.1  mrg     case BUILT_IN_ATOMIC_NAND_FETCH_2:
   7925  1.1  mrg     case BUILT_IN_ATOMIC_NAND_FETCH_4:
   7926  1.1  mrg     case BUILT_IN_ATOMIC_NAND_FETCH_8:
   7927  1.1  mrg     case BUILT_IN_ATOMIC_NAND_FETCH_16:
   7928  1.1  mrg       {
   7929  1.1  mrg 	enum built_in_function lib;
   7930  1.1  mrg 	mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
   7931  1.1  mrg 	lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
   7932  1.1  mrg 				       (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
   7933  1.1  mrg 	target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
   7934  1.1  mrg 						 ignore, lib);
   7935  1.1  mrg 	if (target)
   7936  1.1  mrg 	  return target;
   7937  1.1  mrg 	break;
   7938  1.1  mrg       }
   7939  1.1  mrg     case BUILT_IN_ATOMIC_XOR_FETCH_1:
   7940  1.1  mrg     case BUILT_IN_ATOMIC_XOR_FETCH_2:
   7941  1.1  mrg     case BUILT_IN_ATOMIC_XOR_FETCH_4:
   7942  1.1  mrg     case BUILT_IN_ATOMIC_XOR_FETCH_8:
   7943  1.1  mrg     case BUILT_IN_ATOMIC_XOR_FETCH_16:
   7944  1.1  mrg       {
   7945  1.1  mrg 	enum built_in_function lib;
   7946  1.1  mrg 	mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
   7947  1.1  mrg 	lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
   7948  1.1  mrg 				       (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
   7949  1.1  mrg 	target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
   7950  1.1  mrg 						 ignore, lib);
   7951  1.1  mrg 	if (target)
   7952  1.1  mrg 	  return target;
   7953  1.1  mrg 	break;
   7954  1.1  mrg       }
   7955  1.1  mrg     case BUILT_IN_ATOMIC_OR_FETCH_1:
   7956  1.1  mrg     case BUILT_IN_ATOMIC_OR_FETCH_2:
   7957  1.1  mrg     case BUILT_IN_ATOMIC_OR_FETCH_4:
   7958  1.1  mrg     case BUILT_IN_ATOMIC_OR_FETCH_8:
   7959  1.1  mrg     case BUILT_IN_ATOMIC_OR_FETCH_16:
   7960  1.1  mrg       {
   7961  1.1  mrg 	enum built_in_function lib;
   7962  1.1  mrg 	mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
   7963  1.1  mrg 	lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
   7964  1.1  mrg 				       (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
   7965  1.1  mrg 	target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
   7966  1.1  mrg 						 ignore, lib);
   7967  1.1  mrg 	if (target)
   7968  1.1  mrg 	  return target;
   7969  1.1  mrg 	break;
   7970  1.1  mrg       }
   7971  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_ADD_1:
   7972  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_ADD_2:
   7973  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_ADD_4:
   7974  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_ADD_8:
   7975  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_ADD_16:
   7976  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
   7977  1.1  mrg       target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
   7978  1.1  mrg 					       ignore, BUILT_IN_NONE);
   7979  1.1  mrg       if (target)
   7980  1.1  mrg 	return target;
   7981  1.1  mrg       break;
   7982  1.1  mrg 
   7983  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_SUB_1:
   7984  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_SUB_2:
   7985  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_SUB_4:
   7986  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_SUB_8:
   7987  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_SUB_16:
   7988  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
   7989  1.1  mrg       target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
   7990  1.1  mrg 					       ignore, BUILT_IN_NONE);
   7991  1.1  mrg       if (target)
   7992  1.1  mrg 	return target;
   7993  1.1  mrg       break;
   7994  1.1  mrg 
   7995  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_AND_1:
   7996  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_AND_2:
   7997  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_AND_4:
   7998  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_AND_8:
   7999  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_AND_16:
   8000  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
   8001  1.1  mrg       target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
   8002  1.1  mrg 					       ignore, BUILT_IN_NONE);
   8003  1.1  mrg       if (target)
   8004  1.1  mrg 	return target;
   8005  1.1  mrg       break;
   8006  1.1  mrg 
   8007  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_NAND_1:
   8008  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_NAND_2:
   8009  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_NAND_4:
   8010  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_NAND_8:
   8011  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_NAND_16:
   8012  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
   8013  1.1  mrg       target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
   8014  1.1  mrg 					       ignore, BUILT_IN_NONE);
   8015  1.1  mrg       if (target)
   8016  1.1  mrg 	return target;
   8017  1.1  mrg       break;
   8018  1.1  mrg 
   8019  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_XOR_1:
   8020  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_XOR_2:
   8021  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_XOR_4:
   8022  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_XOR_8:
   8023  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_XOR_16:
   8024  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
   8025  1.1  mrg       target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
   8026  1.1  mrg 					       ignore, BUILT_IN_NONE);
   8027  1.1  mrg       if (target)
   8028  1.1  mrg 	return target;
   8029  1.1  mrg       break;
   8030  1.1  mrg 
   8031  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_OR_1:
   8032  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_OR_2:
   8033  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_OR_4:
   8034  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_OR_8:
   8035  1.1  mrg     case BUILT_IN_ATOMIC_FETCH_OR_16:
   8036  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
   8037  1.1  mrg       target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
   8038  1.1  mrg 					       ignore, BUILT_IN_NONE);
   8039  1.1  mrg       if (target)
   8040  1.1  mrg 	return target;
   8041  1.1  mrg       break;
   8042  1.1  mrg 
   8043  1.1  mrg     case BUILT_IN_ATOMIC_TEST_AND_SET:
   8044  1.1  mrg       return expand_builtin_atomic_test_and_set (exp, target);
   8045  1.1  mrg 
   8046  1.1  mrg     case BUILT_IN_ATOMIC_CLEAR:
   8047  1.1  mrg       return expand_builtin_atomic_clear (exp);
   8048  1.1  mrg 
   8049  1.1  mrg     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
   8050  1.1  mrg       return expand_builtin_atomic_always_lock_free (exp);
   8051  1.1  mrg 
   8052  1.1  mrg     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
   8053  1.1  mrg       target = expand_builtin_atomic_is_lock_free (exp);
   8054  1.1  mrg       if (target)
   8055  1.1  mrg         return target;
   8056  1.1  mrg       break;
   8057  1.1  mrg 
   8058  1.1  mrg     case BUILT_IN_ATOMIC_THREAD_FENCE:
   8059  1.1  mrg       expand_builtin_atomic_thread_fence (exp);
   8060  1.1  mrg       return const0_rtx;
   8061  1.1  mrg 
   8062  1.1  mrg     case BUILT_IN_ATOMIC_SIGNAL_FENCE:
   8063  1.1  mrg       expand_builtin_atomic_signal_fence (exp);
   8064  1.1  mrg       return const0_rtx;
   8065  1.1  mrg 
   8066  1.1  mrg     case BUILT_IN_OBJECT_SIZE:
   8067  1.1  mrg     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
   8068  1.1  mrg       return expand_builtin_object_size (exp);
   8069  1.1  mrg 
   8070  1.1  mrg     case BUILT_IN_MEMCPY_CHK:
   8071  1.1  mrg     case BUILT_IN_MEMPCPY_CHK:
   8072  1.1  mrg     case BUILT_IN_MEMMOVE_CHK:
   8073  1.1  mrg     case BUILT_IN_MEMSET_CHK:
   8074  1.1  mrg       target = expand_builtin_memory_chk (exp, target, mode, fcode);
   8075  1.1  mrg       if (target)
   8076  1.1  mrg 	return target;
   8077  1.1  mrg       break;
   8078  1.1  mrg 
   8079  1.1  mrg     case BUILT_IN_STRCPY_CHK:
   8080  1.1  mrg     case BUILT_IN_STPCPY_CHK:
   8081  1.1  mrg     case BUILT_IN_STRNCPY_CHK:
   8082  1.1  mrg     case BUILT_IN_STPNCPY_CHK:
   8083  1.1  mrg     case BUILT_IN_STRCAT_CHK:
   8084  1.1  mrg     case BUILT_IN_STRNCAT_CHK:
   8085  1.1  mrg     case BUILT_IN_SNPRINTF_CHK:
   8086  1.1  mrg     case BUILT_IN_VSNPRINTF_CHK:
   8087  1.1  mrg       maybe_emit_chk_warning (exp, fcode);
   8088  1.1  mrg       break;
   8089  1.1  mrg 
   8090  1.1  mrg     case BUILT_IN_SPRINTF_CHK:
   8091  1.1  mrg     case BUILT_IN_VSPRINTF_CHK:
   8092  1.1  mrg       maybe_emit_sprintf_chk_warning (exp, fcode);
   8093  1.1  mrg       break;
   8094  1.1  mrg 
   8095  1.1  mrg     case BUILT_IN_THREAD_POINTER:
   8096  1.1  mrg       return expand_builtin_thread_pointer (exp, target);
   8097  1.1  mrg 
   8098  1.1  mrg     case BUILT_IN_SET_THREAD_POINTER:
   8099  1.1  mrg       expand_builtin_set_thread_pointer (exp);
   8100  1.1  mrg       return const0_rtx;
   8101  1.1  mrg 
   8102  1.1  mrg     case BUILT_IN_ACC_ON_DEVICE:
   8103  1.1  mrg       /* Do library call, if we failed to expand the builtin when
   8104  1.1  mrg 	 folding.  */
   8105  1.1  mrg       break;
   8106  1.1  mrg 
   8107  1.1  mrg     case BUILT_IN_GOACC_PARLEVEL_ID:
   8108  1.1  mrg     case BUILT_IN_GOACC_PARLEVEL_SIZE:
   8109  1.1  mrg       return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
   8110  1.1  mrg 
   8111  1.1  mrg     case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
   8112  1.1  mrg       return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
   8113  1.1  mrg 
   8114  1.1  mrg     case BUILT_IN_SPECULATION_SAFE_VALUE_1:
   8115  1.1  mrg     case BUILT_IN_SPECULATION_SAFE_VALUE_2:
   8116  1.1  mrg     case BUILT_IN_SPECULATION_SAFE_VALUE_4:
   8117  1.1  mrg     case BUILT_IN_SPECULATION_SAFE_VALUE_8:
   8118  1.1  mrg     case BUILT_IN_SPECULATION_SAFE_VALUE_16:
   8119  1.1  mrg       mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
   8120  1.1  mrg       return expand_speculation_safe_value (mode, exp, target, ignore);
   8121  1.1  mrg 
   8122  1.1  mrg     default:	/* just do library call, if unknown builtin */
   8123  1.1  mrg       break;
   8124  1.1  mrg     }
   8125  1.1  mrg 
   8126  1.1  mrg   /* The switch statement above can drop through to cause the function
   8127  1.1  mrg      to be called normally.  */
   8128  1.1  mrg   return expand_call (exp, target, ignore);
   8129  1.1  mrg }
   8130  1.1  mrg 
   8131  1.1  mrg /* Determine whether a tree node represents a call to a built-in
   8132  1.1  mrg    function.  If the tree T is a call to a built-in function with
   8133  1.1  mrg    the right number of arguments of the appropriate types, return
   8134  1.1  mrg    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
   8135  1.1  mrg    Otherwise the return value is END_BUILTINS.  */
   8136  1.1  mrg 
   8137  1.1  mrg enum built_in_function
   8138  1.1  mrg builtin_mathfn_code (const_tree t)
   8139  1.1  mrg {
   8140  1.1  mrg   const_tree fndecl, arg, parmlist;
   8141  1.1  mrg   const_tree argtype, parmtype;
   8142  1.1  mrg   const_call_expr_arg_iterator iter;
   8143  1.1  mrg 
   8144  1.1  mrg   if (TREE_CODE (t) != CALL_EXPR)
   8145  1.1  mrg     return END_BUILTINS;
   8146  1.1  mrg 
   8147  1.1  mrg   fndecl = get_callee_fndecl (t);
   8148  1.1  mrg   if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
   8149  1.1  mrg       return END_BUILTINS;
   8150  1.1  mrg 
   8151  1.1  mrg   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
   8152  1.1  mrg   init_const_call_expr_arg_iterator (t, &iter);
   8153  1.1  mrg   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
   8154  1.1  mrg     {
   8155  1.1  mrg       /* If a function doesn't take a variable number of arguments,
   8156  1.1  mrg 	 the last element in the list will have type `void'.  */
   8157  1.1  mrg       parmtype = TREE_VALUE (parmlist);
   8158  1.1  mrg       if (VOID_TYPE_P (parmtype))
   8159  1.1  mrg 	{
   8160  1.1  mrg 	  if (more_const_call_expr_args_p (&iter))
   8161  1.1  mrg 	    return END_BUILTINS;
   8162  1.1  mrg 	  return DECL_FUNCTION_CODE (fndecl);
   8163  1.1  mrg 	}
   8164  1.1  mrg 
   8165  1.1  mrg       if (! more_const_call_expr_args_p (&iter))
   8166  1.1  mrg 	return END_BUILTINS;
   8167  1.1  mrg 
   8168  1.1  mrg       arg = next_const_call_expr_arg (&iter);
   8169  1.1  mrg       argtype = TREE_TYPE (arg);
   8170  1.1  mrg 
   8171  1.1  mrg       if (SCALAR_FLOAT_TYPE_P (parmtype))
   8172  1.1  mrg 	{
   8173  1.1  mrg 	  if (! SCALAR_FLOAT_TYPE_P (argtype))
   8174  1.1  mrg 	    return END_BUILTINS;
   8175  1.1  mrg 	}
   8176  1.1  mrg       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
   8177  1.1  mrg 	{
   8178  1.1  mrg 	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
   8179  1.1  mrg 	    return END_BUILTINS;
   8180  1.1  mrg 	}
   8181  1.1  mrg       else if (POINTER_TYPE_P (parmtype))
   8182  1.1  mrg 	{
   8183  1.1  mrg 	  if (! POINTER_TYPE_P (argtype))
   8184  1.1  mrg 	    return END_BUILTINS;
   8185  1.1  mrg 	}
   8186  1.1  mrg       else if (INTEGRAL_TYPE_P (parmtype))
   8187  1.1  mrg 	{
   8188  1.1  mrg 	  if (! INTEGRAL_TYPE_P (argtype))
   8189  1.1  mrg 	    return END_BUILTINS;
   8190  1.1  mrg 	}
   8191  1.1  mrg       else
   8192  1.1  mrg 	return END_BUILTINS;
   8193  1.1  mrg     }
   8194  1.1  mrg 
   8195  1.1  mrg   /* Variable-length argument list.  */
   8196  1.1  mrg   return DECL_FUNCTION_CODE (fndecl);
   8197  1.1  mrg }
   8198  1.1  mrg 
   8199  1.1  mrg /* Fold a call to __builtin_constant_p, if we know its argument ARG will
   8200  1.1  mrg    evaluate to a constant.  */
   8201  1.1  mrg 
   8202  1.1  mrg static tree
   8203  1.1  mrg fold_builtin_constant_p (tree arg)
   8204  1.1  mrg {
   8205  1.1  mrg   /* We return 1 for a numeric type that's known to be a constant
   8206  1.1  mrg      value at compile-time or for an aggregate type that's a
   8207  1.1  mrg      literal constant.  */
   8208  1.1  mrg   STRIP_NOPS (arg);
   8209  1.1  mrg 
   8210  1.1  mrg   /* If we know this is a constant, emit the constant of one.  */
   8211  1.1  mrg   if (CONSTANT_CLASS_P (arg)
   8212  1.1  mrg       || (TREE_CODE (arg) == CONSTRUCTOR
   8213  1.1  mrg 	  && TREE_CONSTANT (arg)))
   8214  1.1  mrg     return integer_one_node;
   8215  1.1  mrg   if (TREE_CODE (arg) == ADDR_EXPR)
   8216  1.1  mrg     {
   8217  1.1  mrg        tree op = TREE_OPERAND (arg, 0);
   8218  1.1  mrg        if (TREE_CODE (op) == STRING_CST
   8219  1.1  mrg 	   || (TREE_CODE (op) == ARRAY_REF
   8220  1.1  mrg 	       && integer_zerop (TREE_OPERAND (op, 1))
   8221  1.1  mrg 	       && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
   8222  1.1  mrg 	 return integer_one_node;
   8223  1.1  mrg     }
   8224  1.1  mrg 
   8225  1.1  mrg   /* If this expression has side effects, show we don't know it to be a
   8226  1.1  mrg      constant.  Likewise if it's a pointer or aggregate type since in
   8227  1.1  mrg      those case we only want literals, since those are only optimized
   8228  1.1  mrg      when generating RTL, not later.
   8229  1.1  mrg      And finally, if we are compiling an initializer, not code, we
   8230  1.1  mrg      need to return a definite result now; there's not going to be any
   8231  1.1  mrg      more optimization done.  */
   8232  1.1  mrg   if (TREE_SIDE_EFFECTS (arg)
   8233  1.1  mrg       || AGGREGATE_TYPE_P (TREE_TYPE (arg))
   8234  1.1  mrg       || POINTER_TYPE_P (TREE_TYPE (arg))
   8235  1.1  mrg       || cfun == 0
   8236  1.1  mrg       || folding_initializer
   8237  1.1  mrg       || force_folding_builtin_constant_p)
   8238  1.1  mrg     return integer_zero_node;
   8239  1.1  mrg 
   8240  1.1  mrg   return NULL_TREE;
   8241  1.1  mrg }
   8242  1.1  mrg 
   8243  1.1  mrg /* Create builtin_expect or builtin_expect_with_probability
   8244  1.1  mrg    with PRED and EXPECTED as its arguments and return it as a truthvalue.
   8245  1.1  mrg    Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
   8246  1.1  mrg    builtin_expect_with_probability instead uses third argument as PROBABILITY
   8247  1.1  mrg    value.  */
   8248  1.1  mrg 
   8249  1.1  mrg static tree
   8250  1.1  mrg build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
   8251  1.1  mrg 				tree predictor, tree probability)
   8252  1.1  mrg {
   8253  1.1  mrg   tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
   8254  1.1  mrg 
   8255  1.1  mrg   fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
   8256  1.1  mrg 			      : BUILT_IN_EXPECT_WITH_PROBABILITY);
   8257  1.1  mrg   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
   8258  1.1  mrg   ret_type = TREE_TYPE (TREE_TYPE (fn));
   8259  1.1  mrg   pred_type = TREE_VALUE (arg_types);
   8260  1.1  mrg   expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
   8261  1.1  mrg 
   8262  1.1  mrg   pred = fold_convert_loc (loc, pred_type, pred);
   8263  1.1  mrg   expected = fold_convert_loc (loc, expected_type, expected);
   8264  1.1  mrg 
   8265  1.1  mrg   if (probability)
   8266  1.1  mrg     call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
   8267  1.1  mrg   else
   8268  1.1  mrg     call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
   8269  1.1  mrg 				     predictor);
   8270  1.1  mrg 
   8271  1.1  mrg   return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
   8272  1.1  mrg 		 build_int_cst (ret_type, 0));
   8273  1.1  mrg }
   8274  1.1  mrg 
   8275  1.1  mrg /* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3.  Return
   8276  1.1  mrg    NULL_TREE if no simplification is possible.  */
   8277  1.1  mrg 
   8278  1.1  mrg tree
   8279  1.1  mrg fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
   8280  1.1  mrg 		     tree arg3)
   8281  1.1  mrg {
   8282  1.1  mrg   tree inner, fndecl, inner_arg0;
   8283  1.1  mrg   enum tree_code code;
   8284  1.1  mrg 
   8285  1.1  mrg   /* Distribute the expected value over short-circuiting operators.
   8286  1.1  mrg      See through the cast from truthvalue_type_node to long.  */
   8287  1.1  mrg   inner_arg0 = arg0;
   8288  1.1  mrg   while (CONVERT_EXPR_P (inner_arg0)
   8289  1.1  mrg 	 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
   8290  1.1  mrg 	 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
   8291  1.1  mrg     inner_arg0 = TREE_OPERAND (inner_arg0, 0);
   8292  1.1  mrg 
   8293  1.1  mrg   /* If this is a builtin_expect within a builtin_expect keep the
   8294  1.1  mrg      inner one.  See through a comparison against a constant.  It
   8295  1.1  mrg      might have been added to create a thruthvalue.  */
   8296  1.1  mrg   inner = inner_arg0;
   8297  1.1  mrg 
   8298  1.1  mrg   if (COMPARISON_CLASS_P (inner)
   8299  1.1  mrg       && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
   8300  1.1  mrg     inner = TREE_OPERAND (inner, 0);
   8301  1.1  mrg 
   8302  1.1  mrg   if (TREE_CODE (inner) == CALL_EXPR
   8303  1.1  mrg       && (fndecl = get_callee_fndecl (inner))
   8304  1.1  mrg       && (fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
   8305  1.1  mrg 	  || fndecl_built_in_p (fndecl, BUILT_IN_EXPECT_WITH_PROBABILITY)))
   8306  1.1  mrg     return arg0;
   8307  1.1  mrg 
   8308  1.1  mrg   inner = inner_arg0;
   8309  1.1  mrg   code = TREE_CODE (inner);
   8310  1.1  mrg   if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
   8311  1.1  mrg     {
   8312  1.1  mrg       tree op0 = TREE_OPERAND (inner, 0);
   8313  1.1  mrg       tree op1 = TREE_OPERAND (inner, 1);
   8314  1.1  mrg       arg1 = save_expr (arg1);
   8315  1.1  mrg 
   8316  1.1  mrg       op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
   8317  1.1  mrg       op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
   8318  1.1  mrg       inner = build2 (code, TREE_TYPE (inner), op0, op1);
   8319  1.1  mrg 
   8320  1.1  mrg       return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
   8321  1.1  mrg     }
   8322  1.1  mrg 
   8323  1.1  mrg   /* If the argument isn't invariant then there's nothing else we can do.  */
   8324  1.1  mrg   if (!TREE_CONSTANT (inner_arg0))
   8325  1.1  mrg     return NULL_TREE;
   8326  1.1  mrg 
   8327  1.1  mrg   /* If we expect that a comparison against the argument will fold to
   8328  1.1  mrg      a constant return the constant.  In practice, this means a true
   8329  1.1  mrg      constant or the address of a non-weak symbol.  */
   8330  1.1  mrg   inner = inner_arg0;
   8331  1.1  mrg   STRIP_NOPS (inner);
   8332  1.1  mrg   if (TREE_CODE (inner) == ADDR_EXPR)
   8333  1.1  mrg     {
   8334  1.1  mrg       do
   8335  1.1  mrg 	{
   8336  1.1  mrg 	  inner = TREE_OPERAND (inner, 0);
   8337  1.1  mrg 	}
   8338  1.1  mrg       while (TREE_CODE (inner) == COMPONENT_REF
   8339  1.1  mrg 	     || TREE_CODE (inner) == ARRAY_REF);
   8340  1.1  mrg       if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
   8341  1.1  mrg 	return NULL_TREE;
   8342  1.1  mrg     }
   8343  1.1  mrg 
   8344  1.1  mrg   /* Otherwise, ARG0 already has the proper type for the return value.  */
   8345  1.1  mrg   return arg0;
   8346  1.1  mrg }
   8347  1.1  mrg 
   8348  1.1  mrg /* Fold a call to __builtin_classify_type with argument ARG.  */
   8349  1.1  mrg 
   8350  1.1  mrg static tree
   8351  1.1  mrg fold_builtin_classify_type (tree arg)
   8352  1.1  mrg {
   8353  1.1  mrg   if (arg == 0)
   8354  1.1  mrg     return build_int_cst (integer_type_node, no_type_class);
   8355  1.1  mrg 
   8356  1.1  mrg   return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
   8357  1.1  mrg }
   8358  1.1  mrg 
   8359  1.1  mrg /* Fold a call EXPR (which may be null) to __builtin_strlen with argument
   8360  1.1  mrg    ARG.  */
   8361  1.1  mrg 
   8362  1.1  mrg static tree
   8363  1.1  mrg fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
   8364  1.1  mrg {
   8365  1.1  mrg   if (!validate_arg (arg, POINTER_TYPE))
   8366  1.1  mrg     return NULL_TREE;
   8367  1.1  mrg   else
   8368  1.1  mrg     {
   8369  1.1  mrg       c_strlen_data lendata = { };
   8370  1.1  mrg       tree len = c_strlen (arg, 0, &lendata);
   8371  1.1  mrg 
   8372  1.1  mrg       if (len)
   8373  1.1  mrg 	return fold_convert_loc (loc, type, len);
   8374  1.1  mrg 
   8375  1.1  mrg       /* TODO: Move this to gimple-ssa-warn-access once the pass runs
   8376  1.1  mrg 	 also early enough to detect invalid reads in multimensional
   8377  1.1  mrg 	 arrays and struct members.  */
   8378  1.1  mrg       if (!lendata.decl)
   8379  1.1  mrg 	 c_strlen (arg, 1, &lendata);
   8380  1.1  mrg 
   8381  1.1  mrg       if (lendata.decl)
   8382  1.1  mrg 	{
   8383  1.1  mrg 	  if (EXPR_HAS_LOCATION (arg))
   8384  1.1  mrg 	    loc = EXPR_LOCATION (arg);
   8385  1.1  mrg 	  else if (loc == UNKNOWN_LOCATION)
   8386  1.1  mrg 	    loc = input_location;
   8387  1.1  mrg 	  warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
   8388  1.1  mrg 	}
   8389  1.1  mrg 
   8390  1.1  mrg       return NULL_TREE;
   8391  1.1  mrg     }
   8392  1.1  mrg }
   8393  1.1  mrg 
   8394  1.1  mrg /* Fold a call to __builtin_inf or __builtin_huge_val.  */
   8395  1.1  mrg 
   8396  1.1  mrg static tree
   8397  1.1  mrg fold_builtin_inf (location_t loc, tree type, int warn)
   8398  1.1  mrg {
   8399  1.1  mrg   REAL_VALUE_TYPE real;
   8400  1.1  mrg 
   8401  1.1  mrg   /* __builtin_inff is intended to be usable to define INFINITY on all
   8402  1.1  mrg      targets.  If an infinity is not available, INFINITY expands "to a
   8403  1.1  mrg      positive constant of type float that overflows at translation
   8404  1.1  mrg      time", footnote "In this case, using INFINITY will violate the
   8405  1.1  mrg      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
   8406  1.1  mrg      Thus we pedwarn to ensure this constraint violation is
   8407  1.1  mrg      diagnosed.  */
   8408  1.1  mrg   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
   8409  1.1  mrg     pedwarn (loc, 0, "target format does not support infinity");
   8410  1.1  mrg 
   8411  1.1  mrg   real_inf (&real);
   8412  1.1  mrg   return build_real (type, real);
   8413  1.1  mrg }
   8414  1.1  mrg 
   8415  1.1  mrg /* Fold function call to builtin sincos, sincosf, or sincosl.  Return
   8416  1.1  mrg    NULL_TREE if no simplification can be made.  */
   8417  1.1  mrg 
   8418  1.1  mrg static tree
   8419  1.1  mrg fold_builtin_sincos (location_t loc,
   8420  1.1  mrg 		     tree arg0, tree arg1, tree arg2)
   8421  1.1  mrg {
   8422  1.1  mrg   tree type;
   8423  1.1  mrg   tree fndecl, call = NULL_TREE;
   8424  1.1  mrg 
   8425  1.1  mrg   if (!validate_arg (arg0, REAL_TYPE)
   8426  1.1  mrg       || !validate_arg (arg1, POINTER_TYPE)
   8427  1.1  mrg       || !validate_arg (arg2, POINTER_TYPE))
   8428  1.1  mrg     return NULL_TREE;
   8429  1.1  mrg 
   8430  1.1  mrg   type = TREE_TYPE (arg0);
   8431  1.1  mrg 
   8432  1.1  mrg   /* Calculate the result when the argument is a constant.  */
   8433  1.1  mrg   built_in_function fn = mathfn_built_in_2 (type, CFN_BUILT_IN_CEXPI);
   8434  1.1  mrg   if (fn == END_BUILTINS)
   8435  1.1  mrg     return NULL_TREE;
   8436  1.1  mrg 
   8437  1.1  mrg   /* Canonicalize sincos to cexpi.  */
   8438  1.1  mrg   if (TREE_CODE (arg0) == REAL_CST)
   8439  1.1  mrg     {
   8440  1.1  mrg       tree complex_type = build_complex_type (type);
   8441  1.1  mrg       call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
   8442  1.1  mrg     }
   8443  1.1  mrg   if (!call)
   8444  1.1  mrg     {
   8445  1.1  mrg       if (!targetm.libc_has_function (function_c99_math_complex, type)
   8446  1.1  mrg 	  || !builtin_decl_implicit_p (fn))
   8447  1.1  mrg 	return NULL_TREE;
   8448  1.1  mrg       fndecl = builtin_decl_explicit (fn);
   8449  1.1  mrg       call = build_call_expr_loc (loc, fndecl, 1, arg0);
   8450  1.1  mrg       call = builtin_save_expr (call);
   8451  1.1  mrg     }
   8452  1.1  mrg 
   8453  1.1  mrg   tree ptype = build_pointer_type (type);
   8454  1.1  mrg   arg1 = fold_convert (ptype, arg1);
   8455  1.1  mrg   arg2 = fold_convert (ptype, arg2);
   8456  1.1  mrg   return build2 (COMPOUND_EXPR, void_type_node,
   8457  1.1  mrg 		 build2 (MODIFY_EXPR, void_type_node,
   8458  1.1  mrg 			 build_fold_indirect_ref_loc (loc, arg1),
   8459  1.1  mrg 			 fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
   8460  1.1  mrg 		 build2 (MODIFY_EXPR, void_type_node,
   8461  1.1  mrg 			 build_fold_indirect_ref_loc (loc, arg2),
   8462  1.1  mrg 			 fold_build1_loc (loc, REALPART_EXPR, type, call)));
   8463  1.1  mrg }
   8464  1.1  mrg 
   8465  1.1  mrg /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
   8466  1.1  mrg    Return NULL_TREE if no simplification can be made.  */
   8467  1.1  mrg 
   8468  1.1  mrg static tree
   8469  1.1  mrg fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
   8470  1.1  mrg {
   8471  1.1  mrg   if (!validate_arg (arg1, POINTER_TYPE)
   8472  1.1  mrg       || !validate_arg (arg2, POINTER_TYPE)
   8473  1.1  mrg       || !validate_arg (len, INTEGER_TYPE))
   8474  1.1  mrg     return NULL_TREE;
   8475  1.1  mrg 
   8476  1.1  mrg   /* If the LEN parameter is zero, return zero.  */
   8477  1.1  mrg   if (integer_zerop (len))
   8478  1.1  mrg     return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
   8479  1.1  mrg 			      arg1, arg2);
   8480  1.1  mrg 
   8481  1.1  mrg   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
   8482  1.1  mrg   if (operand_equal_p (arg1, arg2, 0))
   8483  1.1  mrg     return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
   8484  1.1  mrg 
   8485  1.1  mrg   /* If len parameter is one, return an expression corresponding to
   8486  1.1  mrg      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
   8487  1.1  mrg   if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
   8488  1.1  mrg     {
   8489  1.1  mrg       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
   8490  1.1  mrg       tree cst_uchar_ptr_node
   8491  1.1  mrg 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
   8492  1.1  mrg 
   8493  1.1  mrg       tree ind1
   8494  1.1  mrg 	= fold_convert_loc (loc, integer_type_node,
   8495  1.1  mrg 			    build1 (INDIRECT_REF, cst_uchar_node,
   8496  1.1  mrg 				    fold_convert_loc (loc,
   8497  1.1  mrg 						      cst_uchar_ptr_node,
   8498  1.1  mrg 						      arg1)));
   8499  1.1  mrg       tree ind2
   8500  1.1  mrg 	= fold_convert_loc (loc, integer_type_node,
   8501  1.1  mrg 			    build1 (INDIRECT_REF, cst_uchar_node,
   8502  1.1  mrg 				    fold_convert_loc (loc,
   8503  1.1  mrg 						      cst_uchar_ptr_node,
   8504  1.1  mrg 						      arg2)));
   8505  1.1  mrg       return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
   8506  1.1  mrg     }
   8507  1.1  mrg 
   8508  1.1  mrg   return NULL_TREE;
   8509  1.1  mrg }
   8510  1.1  mrg 
   8511  1.1  mrg /* Fold a call to builtin isascii with argument ARG.  */
   8512  1.1  mrg 
   8513  1.1  mrg static tree
   8514  1.1  mrg fold_builtin_isascii (location_t loc, tree arg)
   8515  1.1  mrg {
   8516  1.1  mrg   if (!validate_arg (arg, INTEGER_TYPE))
   8517  1.1  mrg     return NULL_TREE;
   8518  1.1  mrg   else
   8519  1.1  mrg     {
   8520  1.1  mrg       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
   8521  1.1  mrg       arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
   8522  1.1  mrg 			 build_int_cst (integer_type_node,
   8523  1.1  mrg 					~ (unsigned HOST_WIDE_INT) 0x7f));
   8524  1.1  mrg       return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
   8525  1.1  mrg 			      arg, integer_zero_node);
   8526  1.1  mrg     }
   8527  1.1  mrg }
   8528  1.1  mrg 
   8529  1.1  mrg /* Fold a call to builtin toascii with argument ARG.  */
   8530  1.1  mrg 
   8531  1.1  mrg static tree
   8532  1.1  mrg fold_builtin_toascii (location_t loc, tree arg)
   8533  1.1  mrg {
   8534  1.1  mrg   if (!validate_arg (arg, INTEGER_TYPE))
   8535  1.1  mrg     return NULL_TREE;
   8536  1.1  mrg 
   8537  1.1  mrg   /* Transform toascii(c) -> (c & 0x7f).  */
   8538  1.1  mrg   return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
   8539  1.1  mrg 			  build_int_cst (integer_type_node, 0x7f));
   8540  1.1  mrg }
   8541  1.1  mrg 
   8542  1.1  mrg /* Fold a call to builtin isdigit with argument ARG.  */
   8543  1.1  mrg 
   8544  1.1  mrg static tree
   8545  1.1  mrg fold_builtin_isdigit (location_t loc, tree arg)
   8546  1.1  mrg {
   8547  1.1  mrg   if (!validate_arg (arg, INTEGER_TYPE))
   8548  1.1  mrg     return NULL_TREE;
   8549  1.1  mrg   else
   8550  1.1  mrg     {
   8551  1.1  mrg       /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
   8552  1.1  mrg       /* According to the C standard, isdigit is unaffected by locale.
   8553  1.1  mrg 	 However, it definitely is affected by the target character set.  */
   8554  1.1  mrg       unsigned HOST_WIDE_INT target_digit0
   8555  1.1  mrg 	= lang_hooks.to_target_charset ('0');
   8556  1.1  mrg 
   8557  1.1  mrg       if (target_digit0 == 0)
   8558  1.1  mrg 	return NULL_TREE;
   8559  1.1  mrg 
   8560  1.1  mrg       arg = fold_convert_loc (loc, unsigned_type_node, arg);
   8561  1.1  mrg       arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
   8562  1.1  mrg 			 build_int_cst (unsigned_type_node, target_digit0));
   8563  1.1  mrg       return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
   8564  1.1  mrg 			  build_int_cst (unsigned_type_node, 9));
   8565  1.1  mrg     }
   8566  1.1  mrg }
   8567  1.1  mrg 
   8568  1.1  mrg /* Fold a call to fabs, fabsf or fabsl with argument ARG.  */
   8569  1.1  mrg 
   8570  1.1  mrg static tree
   8571  1.1  mrg fold_builtin_fabs (location_t loc, tree arg, tree type)
   8572  1.1  mrg {
   8573  1.1  mrg   if (!validate_arg (arg, REAL_TYPE))
   8574  1.1  mrg     return NULL_TREE;
   8575  1.1  mrg 
   8576  1.1  mrg   arg = fold_convert_loc (loc, type, arg);
   8577  1.1  mrg   return fold_build1_loc (loc, ABS_EXPR, type, arg);
   8578  1.1  mrg }
   8579  1.1  mrg 
   8580  1.1  mrg /* Fold a call to abs, labs, llabs or imaxabs with argument ARG.  */
   8581  1.1  mrg 
   8582  1.1  mrg static tree
   8583  1.1  mrg fold_builtin_abs (location_t loc, tree arg, tree type)
   8584  1.1  mrg {
   8585  1.1  mrg   if (!validate_arg (arg, INTEGER_TYPE))
   8586  1.1  mrg     return NULL_TREE;
   8587  1.1  mrg 
   8588  1.1  mrg   arg = fold_convert_loc (loc, type, arg);
   8589  1.1  mrg   return fold_build1_loc (loc, ABS_EXPR, type, arg);
   8590  1.1  mrg }
   8591  1.1  mrg 
   8592  1.1  mrg /* Fold a call to builtin carg(a+bi) -> atan2(b,a).  */
   8593  1.1  mrg 
   8594  1.1  mrg static tree
   8595  1.1  mrg fold_builtin_carg (location_t loc, tree arg, tree type)
   8596  1.1  mrg {
   8597  1.1  mrg   if (validate_arg (arg, COMPLEX_TYPE)
   8598  1.1  mrg       && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
   8599  1.1  mrg     {
   8600  1.1  mrg       tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
   8601  1.1  mrg 
   8602  1.1  mrg       if (atan2_fn)
   8603  1.1  mrg         {
   8604  1.1  mrg   	  tree new_arg = builtin_save_expr (arg);
   8605  1.1  mrg 	  tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
   8606  1.1  mrg 	  tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
   8607  1.1  mrg 	  return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
   8608  1.1  mrg 	}
   8609  1.1  mrg     }
   8610  1.1  mrg 
   8611  1.1  mrg   return NULL_TREE;
   8612  1.1  mrg }
   8613  1.1  mrg 
   8614  1.1  mrg /* Fold a call to builtin frexp, we can assume the base is 2.  */
   8615  1.1  mrg 
   8616  1.1  mrg static tree
   8617  1.1  mrg fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
   8618  1.1  mrg {
   8619  1.1  mrg   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
   8620  1.1  mrg     return NULL_TREE;
   8621  1.1  mrg 
   8622  1.1  mrg   STRIP_NOPS (arg0);
   8623  1.1  mrg 
   8624  1.1  mrg   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
   8625  1.1  mrg     return NULL_TREE;
   8626  1.1  mrg 
   8627  1.1  mrg   arg1 = build_fold_indirect_ref_loc (loc, arg1);
   8628  1.1  mrg 
   8629  1.1  mrg   /* Proceed if a valid pointer type was passed in.  */
   8630  1.1  mrg   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
   8631  1.1  mrg     {
   8632  1.1  mrg       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
   8633  1.1  mrg       tree frac, exp;
   8634  1.1  mrg 
   8635  1.1  mrg       switch (value->cl)
   8636  1.1  mrg       {
   8637  1.1  mrg       case rvc_zero:
   8638  1.1  mrg       case rvc_nan:
   8639  1.1  mrg       case rvc_inf:
   8640  1.1  mrg 	/* For +-0, return (*exp = 0, +-0).  */
   8641  1.1  mrg 	/* For +-NaN or +-Inf, *exp is unspecified, but something should
   8642  1.1  mrg 	   be stored there so that it isn't read from uninitialized object.
   8643  1.1  mrg 	   As glibc and newlib store *exp = 0 for +-Inf/NaN, storing
   8644  1.1  mrg 	   0 here as well is easiest.  */
   8645  1.1  mrg 	exp = integer_zero_node;
   8646  1.1  mrg 	frac = arg0;
   8647  1.1  mrg 	break;
   8648  1.1  mrg       case rvc_normal:
   8649  1.1  mrg 	{
   8650  1.1  mrg 	  /* Since the frexp function always expects base 2, and in
   8651  1.1  mrg 	     GCC normalized significands are already in the range
   8652  1.1  mrg 	     [0.5, 1.0), we have exactly what frexp wants.  */
   8653  1.1  mrg 	  REAL_VALUE_TYPE frac_rvt = *value;
   8654  1.1  mrg 	  SET_REAL_EXP (&frac_rvt, 0);
   8655  1.1  mrg 	  frac = build_real (rettype, frac_rvt);
   8656  1.1  mrg 	  exp = build_int_cst (integer_type_node, REAL_EXP (value));
   8657  1.1  mrg 	}
   8658  1.1  mrg 	break;
   8659  1.1  mrg       default:
   8660  1.1  mrg 	gcc_unreachable ();
   8661  1.1  mrg       }
   8662  1.1  mrg 
   8663  1.1  mrg       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
   8664  1.1  mrg       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
   8665  1.1  mrg       TREE_SIDE_EFFECTS (arg1) = 1;
   8666  1.1  mrg       return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
   8667  1.1  mrg     }
   8668  1.1  mrg 
   8669  1.1  mrg   return NULL_TREE;
   8670  1.1  mrg }
   8671  1.1  mrg 
   8672  1.1  mrg /* Fold a call to builtin modf.  */
   8673  1.1  mrg 
   8674  1.1  mrg static tree
   8675  1.1  mrg fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
   8676  1.1  mrg {
   8677  1.1  mrg   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
   8678  1.1  mrg     return NULL_TREE;
   8679  1.1  mrg 
   8680  1.1  mrg   STRIP_NOPS (arg0);
   8681  1.1  mrg 
   8682  1.1  mrg   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
   8683  1.1  mrg     return NULL_TREE;
   8684  1.1  mrg 
   8685  1.1  mrg   arg1 = build_fold_indirect_ref_loc (loc, arg1);
   8686  1.1  mrg 
   8687  1.1  mrg   /* Proceed if a valid pointer type was passed in.  */
   8688  1.1  mrg   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
   8689  1.1  mrg     {
   8690  1.1  mrg       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
   8691  1.1  mrg       REAL_VALUE_TYPE trunc, frac;
   8692  1.1  mrg 
   8693  1.1  mrg       switch (value->cl)
   8694  1.1  mrg       {
   8695  1.1  mrg       case rvc_nan:
   8696  1.1  mrg       case rvc_zero:
   8697  1.1  mrg 	/* For +-NaN or +-0, return (*arg1 = arg0, arg0).  */
   8698  1.1  mrg 	trunc = frac = *value;
   8699  1.1  mrg 	break;
   8700  1.1  mrg       case rvc_inf:
   8701  1.1  mrg 	/* For +-Inf, return (*arg1 = arg0, +-0).  */
   8702  1.1  mrg 	frac = dconst0;
   8703  1.1  mrg 	frac.sign = value->sign;
   8704  1.1  mrg 	trunc = *value;
   8705  1.1  mrg 	break;
   8706  1.1  mrg       case rvc_normal:
   8707  1.1  mrg 	/* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)).  */
   8708  1.1  mrg 	real_trunc (&trunc, VOIDmode, value);
   8709  1.1  mrg 	real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
   8710  1.1  mrg 	/* If the original number was negative and already
   8711  1.1  mrg 	   integral, then the fractional part is -0.0.  */
   8712  1.1  mrg 	if (value->sign && frac.cl == rvc_zero)
   8713  1.1  mrg 	  frac.sign = value->sign;
   8714  1.1  mrg 	break;
   8715  1.1  mrg       }
   8716  1.1  mrg 
   8717  1.1  mrg       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
   8718  1.1  mrg       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
   8719  1.1  mrg 			  build_real (rettype, trunc));
   8720  1.1  mrg       TREE_SIDE_EFFECTS (arg1) = 1;
   8721  1.1  mrg       return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
   8722  1.1  mrg 			  build_real (rettype, frac));
   8723  1.1  mrg     }
   8724  1.1  mrg 
   8725  1.1  mrg   return NULL_TREE;
   8726  1.1  mrg }
   8727  1.1  mrg 
   8728  1.1  mrg /* Given a location LOC, an interclass builtin function decl FNDECL
   8729  1.1  mrg    and its single argument ARG, return an folded expression computing
   8730  1.1  mrg    the same, or NULL_TREE if we either couldn't or didn't want to fold
   8731  1.1  mrg    (the latter happen if there's an RTL instruction available).  */
   8732  1.1  mrg 
   8733  1.1  mrg static tree
   8734  1.1  mrg fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
   8735  1.1  mrg {
   8736  1.1  mrg   machine_mode mode;
   8737  1.1  mrg 
   8738  1.1  mrg   if (!validate_arg (arg, REAL_TYPE))
   8739  1.1  mrg     return NULL_TREE;
   8740  1.1  mrg 
   8741  1.1  mrg   if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
   8742  1.1  mrg     return NULL_TREE;
   8743  1.1  mrg 
   8744  1.1  mrg   mode = TYPE_MODE (TREE_TYPE (arg));
   8745  1.1  mrg 
   8746  1.1  mrg   bool is_ibm_extended = MODE_COMPOSITE_P (mode);
   8747  1.1  mrg 
   8748  1.1  mrg   /* If there is no optab, try generic code.  */
   8749  1.1  mrg   switch (DECL_FUNCTION_CODE (fndecl))
   8750  1.1  mrg     {
   8751  1.1  mrg       tree result;
   8752  1.1  mrg 
   8753  1.1  mrg     CASE_FLT_FN (BUILT_IN_ISINF):
   8754  1.1  mrg       {
   8755  1.1  mrg 	/* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
   8756  1.1  mrg 	tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
   8757  1.1  mrg 	tree type = TREE_TYPE (arg);
   8758  1.1  mrg 	REAL_VALUE_TYPE r;
   8759  1.1  mrg 	char buf[128];
   8760  1.1  mrg 
   8761  1.1  mrg 	if (is_ibm_extended)
   8762  1.1  mrg 	  {
   8763  1.1  mrg 	    /* NaN and Inf are encoded in the high-order double value
   8764  1.1  mrg 	       only.  The low-order value is not significant.  */
   8765  1.1  mrg 	    type = double_type_node;
   8766  1.1  mrg 	    mode = DFmode;
   8767  1.1  mrg 	    arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
   8768  1.1  mrg 	  }
   8769  1.1  mrg 	get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
   8770  1.1  mrg 	real_from_string3 (&r, buf, mode);
   8771  1.1  mrg 	result = build_call_expr (isgr_fn, 2,
   8772  1.1  mrg 				  fold_build1_loc (loc, ABS_EXPR, type, arg),
   8773  1.1  mrg 				  build_real (type, r));
   8774  1.1  mrg 	return result;
   8775  1.1  mrg       }
   8776  1.1  mrg     CASE_FLT_FN (BUILT_IN_FINITE):
   8777  1.1  mrg     case BUILT_IN_ISFINITE:
   8778  1.1  mrg       {
   8779  1.1  mrg 	/* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
   8780  1.1  mrg 	tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
   8781  1.1  mrg 	tree type = TREE_TYPE (arg);
   8782  1.1  mrg 	REAL_VALUE_TYPE r;
   8783  1.1  mrg 	char buf[128];
   8784  1.1  mrg 
   8785  1.1  mrg 	if (is_ibm_extended)
   8786  1.1  mrg 	  {
   8787  1.1  mrg 	    /* NaN and Inf are encoded in the high-order double value
   8788  1.1  mrg 	       only.  The low-order value is not significant.  */
   8789  1.1  mrg 	    type = double_type_node;
   8790  1.1  mrg 	    mode = DFmode;
   8791  1.1  mrg 	    arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
   8792  1.1  mrg 	  }
   8793  1.1  mrg 	get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
   8794  1.1  mrg 	real_from_string3 (&r, buf, mode);
   8795  1.1  mrg 	result = build_call_expr (isle_fn, 2,
   8796  1.1  mrg 				  fold_build1_loc (loc, ABS_EXPR, type, arg),
   8797  1.1  mrg 				  build_real (type, r));
   8798  1.1  mrg 	/*result = fold_build2_loc (loc, UNGT_EXPR,
   8799  1.1  mrg 				  TREE_TYPE (TREE_TYPE (fndecl)),
   8800  1.1  mrg 				  fold_build1_loc (loc, ABS_EXPR, type, arg),
   8801  1.1  mrg 				  build_real (type, r));
   8802  1.1  mrg 	result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
   8803  1.1  mrg 				  TREE_TYPE (TREE_TYPE (fndecl)),
   8804  1.1  mrg 				  result);*/
   8805  1.1  mrg 	return result;
   8806  1.1  mrg       }
   8807  1.1  mrg     case BUILT_IN_ISNORMAL:
   8808  1.1  mrg       {
   8809  1.1  mrg 	/* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
   8810  1.1  mrg 	   islessequal(fabs(x),DBL_MAX).  */
   8811  1.1  mrg 	tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
   8812  1.1  mrg 	tree type = TREE_TYPE (arg);
   8813  1.1  mrg 	tree orig_arg, max_exp, min_exp;
   8814  1.1  mrg 	machine_mode orig_mode = mode;
   8815  1.1  mrg 	REAL_VALUE_TYPE rmax, rmin;
   8816  1.1  mrg 	char buf[128];
   8817  1.1  mrg 
   8818  1.1  mrg 	orig_arg = arg = builtin_save_expr (arg);
   8819  1.1  mrg 	if (is_ibm_extended)
   8820  1.1  mrg 	  {
   8821  1.1  mrg 	    /* Use double to test the normal range of IBM extended
   8822  1.1  mrg 	       precision.  Emin for IBM extended precision is
   8823  1.1  mrg 	       different to emin for IEEE double, being 53 higher
   8824  1.1  mrg 	       since the low double exponent is at least 53 lower
   8825  1.1  mrg 	       than the high double exponent.  */
   8826  1.1  mrg 	    type = double_type_node;
   8827  1.1  mrg 	    mode = DFmode;
   8828  1.1  mrg 	    arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
   8829  1.1  mrg 	  }
   8830  1.1  mrg 	arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
   8831  1.1  mrg 
   8832  1.1  mrg 	get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
   8833  1.1  mrg 	real_from_string3 (&rmax, buf, mode);
   8834  1.1  mrg 	if (DECIMAL_FLOAT_MODE_P (mode))
   8835  1.1  mrg 	  sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
   8836  1.1  mrg 	else
   8837  1.1  mrg 	  sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
   8838  1.1  mrg 	real_from_string3 (&rmin, buf, orig_mode);
   8839  1.1  mrg 	max_exp = build_real (type, rmax);
   8840  1.1  mrg 	min_exp = build_real (type, rmin);
   8841  1.1  mrg 
   8842  1.1  mrg 	max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
   8843  1.1  mrg 	if (is_ibm_extended)
   8844  1.1  mrg 	  {
   8845  1.1  mrg 	    /* Testing the high end of the range is done just using
   8846  1.1  mrg 	       the high double, using the same test as isfinite().
   8847  1.1  mrg 	       For the subnormal end of the range we first test the
   8848  1.1  mrg 	       high double, then if its magnitude is equal to the
   8849  1.1  mrg 	       limit of 0x1p-969, we test whether the low double is
   8850  1.1  mrg 	       non-zero and opposite sign to the high double.  */
   8851  1.1  mrg 	    tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
   8852  1.1  mrg 	    tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
   8853  1.1  mrg 	    tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
   8854  1.1  mrg 	    tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
   8855  1.1  mrg 				       arg, min_exp);
   8856  1.1  mrg 	    tree as_complex = build1 (VIEW_CONVERT_EXPR,
   8857  1.1  mrg 				      complex_double_type_node, orig_arg);
   8858  1.1  mrg 	    tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
   8859  1.1  mrg 	    tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
   8860  1.1  mrg 	    tree zero = build_real (type, dconst0);
   8861  1.1  mrg 	    tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
   8862  1.1  mrg 	    tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
   8863  1.1  mrg 	    tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
   8864  1.1  mrg 	    tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
   8865  1.1  mrg 				      fold_build3 (COND_EXPR,
   8866  1.1  mrg 						   integer_type_node,
   8867  1.1  mrg 						   hilt, logt, lolt));
   8868  1.1  mrg 	    eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
   8869  1.1  mrg 				  eq_min, ok_lo);
   8870  1.1  mrg 	    min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
   8871  1.1  mrg 				   gt_min, eq_min);
   8872  1.1  mrg 	  }
   8873  1.1  mrg 	else
   8874  1.1  mrg 	  {
   8875  1.1  mrg 	    tree const isge_fn
   8876  1.1  mrg 	      = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
   8877  1.1  mrg 	    min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
   8878  1.1  mrg 	  }
   8879  1.1  mrg 	result = fold_build2 (BIT_AND_EXPR, integer_type_node,
   8880  1.1  mrg 			      max_exp, min_exp);
   8881  1.1  mrg 	return result;
   8882  1.1  mrg       }
   8883  1.1  mrg     default:
   8884  1.1  mrg       break;
   8885  1.1  mrg     }
   8886  1.1  mrg 
   8887  1.1  mrg   return NULL_TREE;
   8888  1.1  mrg }
   8889  1.1  mrg 
   8890  1.1  mrg /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
   8891  1.1  mrg    ARG is the argument for the call.  */
   8892  1.1  mrg 
   8893  1.1  mrg static tree
   8894  1.1  mrg fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
   8895  1.1  mrg {
   8896  1.1  mrg   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   8897  1.1  mrg 
   8898  1.1  mrg   if (!validate_arg (arg, REAL_TYPE))
   8899  1.1  mrg     return NULL_TREE;
   8900  1.1  mrg 
   8901  1.1  mrg   switch (builtin_index)
   8902  1.1  mrg     {
   8903  1.1  mrg     case BUILT_IN_ISINF:
   8904  1.1  mrg       if (tree_expr_infinite_p (arg))
   8905  1.1  mrg 	return omit_one_operand_loc (loc, type, integer_one_node, arg);
   8906  1.1  mrg       if (!tree_expr_maybe_infinite_p (arg))
   8907  1.1  mrg 	return omit_one_operand_loc (loc, type, integer_zero_node, arg);
   8908  1.1  mrg       return NULL_TREE;
   8909  1.1  mrg 
   8910  1.1  mrg     case BUILT_IN_ISINF_SIGN:
   8911  1.1  mrg       {
   8912  1.1  mrg 	/* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
   8913  1.1  mrg 	/* In a boolean context, GCC will fold the inner COND_EXPR to
   8914  1.1  mrg 	   1.  So e.g. "if (isinf_sign(x))" would be folded to just
   8915  1.1  mrg 	   "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
   8916  1.1  mrg 	tree signbit_fn = builtin_decl_explicit (BUILT_IN_SIGNBIT);
   8917  1.1  mrg 	tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
   8918  1.1  mrg 	tree tmp = NULL_TREE;
   8919  1.1  mrg 
   8920  1.1  mrg 	arg = builtin_save_expr (arg);
   8921  1.1  mrg 
   8922  1.1  mrg 	if (signbit_fn && isinf_fn)
   8923  1.1  mrg 	  {
   8924  1.1  mrg 	    tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
   8925  1.1  mrg 	    tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
   8926  1.1  mrg 
   8927  1.1  mrg 	    signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
   8928  1.1  mrg 					signbit_call, integer_zero_node);
   8929  1.1  mrg 	    isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
   8930  1.1  mrg 				      isinf_call, integer_zero_node);
   8931  1.1  mrg 
   8932  1.1  mrg 	    tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
   8933  1.1  mrg 			       integer_minus_one_node, integer_one_node);
   8934  1.1  mrg 	    tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
   8935  1.1  mrg 			       isinf_call, tmp,
   8936  1.1  mrg 			       integer_zero_node);
   8937  1.1  mrg 	  }
   8938  1.1  mrg 
   8939  1.1  mrg 	return tmp;
   8940  1.1  mrg       }
   8941  1.1  mrg 
   8942  1.1  mrg     case BUILT_IN_ISFINITE:
   8943  1.1  mrg       if (tree_expr_finite_p (arg))
   8944  1.1  mrg 	return omit_one_operand_loc (loc, type, integer_one_node, arg);
   8945  1.1  mrg       if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
   8946  1.1  mrg 	return omit_one_operand_loc (loc, type, integer_zero_node, arg);
   8947  1.1  mrg       return NULL_TREE;
   8948  1.1  mrg 
   8949  1.1  mrg     case BUILT_IN_ISNAN:
   8950  1.1  mrg       if (tree_expr_nan_p (arg))
   8951  1.1  mrg 	return omit_one_operand_loc (loc, type, integer_one_node, arg);
   8952  1.1  mrg       if (!tree_expr_maybe_nan_p (arg))
   8953  1.1  mrg 	return omit_one_operand_loc (loc, type, integer_zero_node, arg);
   8954  1.1  mrg 
   8955  1.1  mrg       {
   8956  1.1  mrg 	bool is_ibm_extended = MODE_COMPOSITE_P (TYPE_MODE (TREE_TYPE (arg)));
   8957  1.1  mrg 	if (is_ibm_extended)
   8958  1.1  mrg 	  {
   8959  1.1  mrg 	    /* NaN and Inf are encoded in the high-order double value
   8960  1.1  mrg 	       only.  The low-order value is not significant.  */
   8961  1.1  mrg 	    arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
   8962  1.1  mrg 	  }
   8963  1.1  mrg       }
   8964  1.1  mrg       arg = builtin_save_expr (arg);
   8965  1.1  mrg       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
   8966  1.1  mrg 
   8967  1.1  mrg     default:
   8968  1.1  mrg       gcc_unreachable ();
   8969  1.1  mrg     }
   8970  1.1  mrg }
   8971  1.1  mrg 
   8972  1.1  mrg /* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
   8973  1.1  mrg    This builtin will generate code to return the appropriate floating
   8974  1.1  mrg    point classification depending on the value of the floating point
   8975  1.1  mrg    number passed in.  The possible return values must be supplied as
   8976  1.1  mrg    int arguments to the call in the following order: FP_NAN, FP_INFINITE,
   8977  1.1  mrg    FP_NORMAL, FP_SUBNORMAL and FP_ZERO.  The ellipses is for exactly
   8978  1.1  mrg    one floating point argument which is "type generic".  */
   8979  1.1  mrg 
   8980  1.1  mrg static tree
   8981  1.1  mrg fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
   8982  1.1  mrg {
   8983  1.1  mrg   tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
   8984  1.1  mrg     arg, type, res, tmp;
   8985  1.1  mrg   machine_mode mode;
   8986  1.1  mrg   REAL_VALUE_TYPE r;
   8987  1.1  mrg   char buf[128];
   8988  1.1  mrg 
   8989  1.1  mrg   /* Verify the required arguments in the original call.  */
   8990  1.1  mrg   if (nargs != 6
   8991  1.1  mrg       || !validate_arg (args[0], INTEGER_TYPE)
   8992  1.1  mrg       || !validate_arg (args[1], INTEGER_TYPE)
   8993  1.1  mrg       || !validate_arg (args[2], INTEGER_TYPE)
   8994  1.1  mrg       || !validate_arg (args[3], INTEGER_TYPE)
   8995  1.1  mrg       || !validate_arg (args[4], INTEGER_TYPE)
   8996  1.1  mrg       || !validate_arg (args[5], REAL_TYPE))
   8997  1.1  mrg     return NULL_TREE;
   8998  1.1  mrg 
   8999  1.1  mrg   fp_nan = args[0];
   9000  1.1  mrg   fp_infinite = args[1];
   9001  1.1  mrg   fp_normal = args[2];
   9002  1.1  mrg   fp_subnormal = args[3];
   9003  1.1  mrg   fp_zero = args[4];
   9004  1.1  mrg   arg = args[5];
   9005  1.1  mrg   type = TREE_TYPE (arg);
   9006  1.1  mrg   mode = TYPE_MODE (type);
   9007  1.1  mrg   arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
   9008  1.1  mrg 
   9009  1.1  mrg   /* fpclassify(x) ->
   9010  1.1  mrg        isnan(x) ? FP_NAN :
   9011  1.1  mrg          (fabs(x) == Inf ? FP_INFINITE :
   9012  1.1  mrg 	   (fabs(x) >= DBL_MIN ? FP_NORMAL :
   9013  1.1  mrg 	     (x == 0 ? FP_ZERO : FP_SUBNORMAL))).  */
   9014  1.1  mrg 
   9015  1.1  mrg   tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   9016  1.1  mrg 			 build_real (type, dconst0));
   9017  1.1  mrg   res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
   9018  1.1  mrg 			 tmp, fp_zero, fp_subnormal);
   9019  1.1  mrg 
   9020  1.1  mrg   if (DECIMAL_FLOAT_MODE_P (mode))
   9021  1.1  mrg     sprintf (buf, "1E%d", REAL_MODE_FORMAT (mode)->emin - 1);
   9022  1.1  mrg   else
   9023  1.1  mrg     sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
   9024  1.1  mrg   real_from_string3 (&r, buf, mode);
   9025  1.1  mrg   tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
   9026  1.1  mrg 			 arg, build_real (type, r));
   9027  1.1  mrg   res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   9028  1.1  mrg 			 fp_normal, res);
   9029  1.1  mrg 
   9030  1.1  mrg   if (tree_expr_maybe_infinite_p (arg))
   9031  1.1  mrg     {
   9032  1.1  mrg       real_inf (&r);
   9033  1.1  mrg       tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   9034  1.1  mrg 			     build_real (type, r));
   9035  1.1  mrg       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   9036  1.1  mrg 			     fp_infinite, res);
   9037  1.1  mrg     }
   9038  1.1  mrg 
   9039  1.1  mrg   if (tree_expr_maybe_nan_p (arg))
   9040  1.1  mrg     {
   9041  1.1  mrg       tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
   9042  1.1  mrg       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   9043  1.1  mrg 			     res, fp_nan);
   9044  1.1  mrg     }
   9045  1.1  mrg 
   9046  1.1  mrg   return res;
   9047  1.1  mrg }
   9048  1.1  mrg 
   9049  1.1  mrg /* Fold a call to an unordered comparison function such as
   9050  1.1  mrg    __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
   9051  1.1  mrg    being called and ARG0 and ARG1 are the arguments for the call.
   9052  1.1  mrg    UNORDERED_CODE and ORDERED_CODE are comparison codes that give
   9053  1.1  mrg    the opposite of the desired result.  UNORDERED_CODE is used
   9054  1.1  mrg    for modes that can hold NaNs and ORDERED_CODE is used for
   9055  1.1  mrg    the rest.  */
   9056  1.1  mrg 
   9057  1.1  mrg static tree
   9058  1.1  mrg fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
   9059  1.1  mrg 			    enum tree_code unordered_code,
   9060  1.1  mrg 			    enum tree_code ordered_code)
   9061  1.1  mrg {
   9062  1.1  mrg   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   9063  1.1  mrg   enum tree_code code;
   9064  1.1  mrg   tree type0, type1;
   9065  1.1  mrg   enum tree_code code0, code1;
   9066  1.1  mrg   tree cmp_type = NULL_TREE;
   9067  1.1  mrg 
   9068  1.1  mrg   type0 = TREE_TYPE (arg0);
   9069  1.1  mrg   type1 = TREE_TYPE (arg1);
   9070  1.1  mrg 
   9071  1.1  mrg   code0 = TREE_CODE (type0);
   9072  1.1  mrg   code1 = TREE_CODE (type1);
   9073  1.1  mrg 
   9074  1.1  mrg   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   9075  1.1  mrg     /* Choose the wider of two real types.  */
   9076  1.1  mrg     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   9077  1.1  mrg       ? type0 : type1;
   9078  1.1  mrg   else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
   9079  1.1  mrg     cmp_type = type0;
   9080  1.1  mrg   else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
   9081  1.1  mrg     cmp_type = type1;
   9082  1.1  mrg 
   9083  1.1  mrg   arg0 = fold_convert_loc (loc, cmp_type, arg0);
   9084  1.1  mrg   arg1 = fold_convert_loc (loc, cmp_type, arg1);
   9085  1.1  mrg 
   9086  1.1  mrg   if (unordered_code == UNORDERED_EXPR)
   9087  1.1  mrg     {
   9088  1.1  mrg       if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
   9089  1.1  mrg 	return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
   9090  1.1  mrg       if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
   9091  1.1  mrg 	return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
   9092  1.1  mrg       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
   9093  1.1  mrg     }
   9094  1.1  mrg 
   9095  1.1  mrg   code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
   9096  1.1  mrg 	 ? unordered_code : ordered_code;
   9097  1.1  mrg   return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
   9098  1.1  mrg 		      fold_build2_loc (loc, code, type, arg0, arg1));
   9099  1.1  mrg }
   9100  1.1  mrg 
   9101  1.1  mrg /* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
   9102  1.1  mrg    arithmetics if it can never overflow, or into internal functions that
   9103  1.1  mrg    return both result of arithmetics and overflowed boolean flag in
   9104  1.1  mrg    a complex integer result, or some other check for overflow.
   9105  1.1  mrg    Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
   9106  1.1  mrg    checking part of that.  */
   9107  1.1  mrg 
   9108  1.1  mrg static tree
   9109  1.1  mrg fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
   9110  1.1  mrg 			     tree arg0, tree arg1, tree arg2)
   9111  1.1  mrg {
   9112  1.1  mrg   enum internal_fn ifn = IFN_LAST;
   9113  1.1  mrg   /* The code of the expression corresponding to the built-in.  */
   9114  1.1  mrg   enum tree_code opcode = ERROR_MARK;
   9115  1.1  mrg   bool ovf_only = false;
   9116  1.1  mrg 
   9117  1.1  mrg   switch (fcode)
   9118  1.1  mrg     {
   9119  1.1  mrg     case BUILT_IN_ADD_OVERFLOW_P:
   9120  1.1  mrg       ovf_only = true;
   9121  1.1  mrg       /* FALLTHRU */
   9122  1.1  mrg     case BUILT_IN_ADD_OVERFLOW:
   9123  1.1  mrg     case BUILT_IN_SADD_OVERFLOW:
   9124  1.1  mrg     case BUILT_IN_SADDL_OVERFLOW:
   9125  1.1  mrg     case BUILT_IN_SADDLL_OVERFLOW:
   9126  1.1  mrg     case BUILT_IN_UADD_OVERFLOW:
   9127  1.1  mrg     case BUILT_IN_UADDL_OVERFLOW:
   9128  1.1  mrg     case BUILT_IN_UADDLL_OVERFLOW:
   9129  1.1  mrg       opcode = PLUS_EXPR;
   9130  1.1  mrg       ifn = IFN_ADD_OVERFLOW;
   9131  1.1  mrg       break;
   9132  1.1  mrg     case BUILT_IN_SUB_OVERFLOW_P:
   9133  1.1  mrg       ovf_only = true;
   9134  1.1  mrg       /* FALLTHRU */
   9135  1.1  mrg     case BUILT_IN_SUB_OVERFLOW:
   9136  1.1  mrg     case BUILT_IN_SSUB_OVERFLOW:
   9137  1.1  mrg     case BUILT_IN_SSUBL_OVERFLOW:
   9138  1.1  mrg     case BUILT_IN_SSUBLL_OVERFLOW:
   9139  1.1  mrg     case BUILT_IN_USUB_OVERFLOW:
   9140  1.1  mrg     case BUILT_IN_USUBL_OVERFLOW:
   9141  1.1  mrg     case BUILT_IN_USUBLL_OVERFLOW:
   9142  1.1  mrg       opcode = MINUS_EXPR;
   9143  1.1  mrg       ifn = IFN_SUB_OVERFLOW;
   9144  1.1  mrg       break;
   9145  1.1  mrg     case BUILT_IN_MUL_OVERFLOW_P:
   9146  1.1  mrg       ovf_only = true;
   9147  1.1  mrg       /* FALLTHRU */
   9148  1.1  mrg     case BUILT_IN_MUL_OVERFLOW:
   9149  1.1  mrg     case BUILT_IN_SMUL_OVERFLOW:
   9150  1.1  mrg     case BUILT_IN_SMULL_OVERFLOW:
   9151  1.1  mrg     case BUILT_IN_SMULLL_OVERFLOW:
   9152  1.1  mrg     case BUILT_IN_UMUL_OVERFLOW:
   9153  1.1  mrg     case BUILT_IN_UMULL_OVERFLOW:
   9154  1.1  mrg     case BUILT_IN_UMULLL_OVERFLOW:
   9155  1.1  mrg       opcode = MULT_EXPR;
   9156  1.1  mrg       ifn = IFN_MUL_OVERFLOW;
   9157  1.1  mrg       break;
   9158  1.1  mrg     default:
   9159  1.1  mrg       gcc_unreachable ();
   9160  1.1  mrg     }
   9161  1.1  mrg 
   9162  1.1  mrg   /* For the "generic" overloads, the first two arguments can have different
   9163  1.1  mrg      types and the last argument determines the target type to use to check
   9164  1.1  mrg      for overflow.  The arguments of the other overloads all have the same
   9165  1.1  mrg      type.  */
   9166  1.1  mrg   tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
   9167  1.1  mrg 
   9168  1.1  mrg   /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
   9169  1.1  mrg      arguments are constant, attempt to fold the built-in call into a constant
   9170  1.1  mrg      expression indicating whether or not it detected an overflow.  */
   9171  1.1  mrg   if (ovf_only
   9172  1.1  mrg       && TREE_CODE (arg0) == INTEGER_CST
   9173  1.1  mrg       && TREE_CODE (arg1) == INTEGER_CST)
   9174  1.1  mrg     /* Perform the computation in the target type and check for overflow.  */
   9175  1.1  mrg     return omit_one_operand_loc (loc, boolean_type_node,
   9176  1.1  mrg 				 arith_overflowed_p (opcode, type, arg0, arg1)
   9177  1.1  mrg 				 ? boolean_true_node : boolean_false_node,
   9178  1.1  mrg 				 arg2);
   9179  1.1  mrg 
   9180  1.1  mrg   tree intres, ovfres;
   9181  1.1  mrg   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
   9182  1.1  mrg     {
   9183  1.1  mrg       intres = fold_binary_loc (loc, opcode, type,
   9184  1.1  mrg 				fold_convert_loc (loc, type, arg0),
   9185  1.1  mrg 				fold_convert_loc (loc, type, arg1));
   9186  1.1  mrg       if (TREE_OVERFLOW (intres))
   9187  1.1  mrg 	intres = drop_tree_overflow (intres);
   9188  1.1  mrg       ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
   9189  1.1  mrg 		? boolean_true_node : boolean_false_node);
   9190  1.1  mrg     }
   9191  1.1  mrg   else
   9192  1.1  mrg     {
   9193  1.1  mrg       tree ctype = build_complex_type (type);
   9194  1.1  mrg       tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   9195  1.1  mrg 						arg0, arg1);
   9196  1.1  mrg       tree tgt;
   9197  1.1  mrg       if (ovf_only)
   9198  1.1  mrg 	{
   9199  1.1  mrg 	  tgt = call;
   9200  1.1  mrg 	  intres = NULL_TREE;
   9201  1.1  mrg 	}
   9202  1.1  mrg       else
   9203  1.1  mrg 	{
   9204  1.1  mrg 	  /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   9205  1.1  mrg 	     as while the call itself is const, the REALPART_EXPR store is
   9206  1.1  mrg 	     certainly not.  And in any case, we want just one call,
   9207  1.1  mrg 	     not multiple and trying to CSE them later.  */
   9208  1.1  mrg 	  TREE_SIDE_EFFECTS (call) = 1;
   9209  1.1  mrg 	  tgt = save_expr (call);
   9210  1.1  mrg 	}
   9211  1.1  mrg       intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   9212  1.1  mrg       ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   9213  1.1  mrg       ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
   9214  1.1  mrg     }
   9215  1.1  mrg 
   9216  1.1  mrg   if (ovf_only)
   9217  1.1  mrg     return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
   9218  1.1  mrg 
   9219  1.1  mrg   tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
   9220  1.1  mrg   tree store
   9221  1.1  mrg     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
   9222  1.1  mrg   return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
   9223  1.1  mrg }
   9224  1.1  mrg 
   9225  1.1  mrg /* Fold a call to __builtin_FILE to a constant string.  */
   9226  1.1  mrg 
   9227  1.1  mrg static inline tree
   9228  1.1  mrg fold_builtin_FILE (location_t loc)
   9229  1.1  mrg {
   9230  1.1  mrg   if (const char *fname = LOCATION_FILE (loc))
   9231  1.1  mrg     {
   9232  1.1  mrg       /* The documentation says this builtin is equivalent to the preprocessor
   9233  1.1  mrg 	 __FILE__ macro so it appears appropriate to use the same file prefix
   9234  1.1  mrg 	 mappings.  */
   9235  1.1  mrg       fname = remap_macro_filename (fname);
   9236  1.1  mrg     return build_string_literal (strlen (fname) + 1, fname);
   9237  1.1  mrg     }
   9238  1.1  mrg 
   9239  1.1  mrg   return build_string_literal (1, "");
   9240  1.1  mrg }
   9241  1.1  mrg 
   9242  1.1  mrg /* Fold a call to __builtin_FUNCTION to a constant string.  */
   9243  1.1  mrg 
   9244  1.1  mrg static inline tree
   9245  1.1  mrg fold_builtin_FUNCTION ()
   9246  1.1  mrg {
   9247  1.1  mrg   const char *name = "";
   9248  1.1  mrg 
   9249  1.1  mrg   if (current_function_decl)
   9250  1.1  mrg     name = lang_hooks.decl_printable_name (current_function_decl, 0);
   9251  1.1  mrg 
   9252  1.1  mrg   return build_string_literal (strlen (name) + 1, name);
   9253  1.1  mrg }
   9254  1.1  mrg 
   9255  1.1  mrg /* Fold a call to __builtin_LINE to an integer constant.  */
   9256  1.1  mrg 
   9257  1.1  mrg static inline tree
   9258  1.1  mrg fold_builtin_LINE (location_t loc, tree type)
   9259  1.1  mrg {
   9260  1.1  mrg   return build_int_cst (type, LOCATION_LINE (loc));
   9261  1.1  mrg }
   9262  1.1  mrg 
   9263  1.1  mrg /* Fold a call to built-in function FNDECL with 0 arguments.
   9264  1.1  mrg    This function returns NULL_TREE if no simplification was possible.  */
   9265  1.1  mrg 
   9266  1.1  mrg static tree
   9267  1.1  mrg fold_builtin_0 (location_t loc, tree fndecl)
   9268  1.1  mrg {
   9269  1.1  mrg   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   9270  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   9271  1.1  mrg   switch (fcode)
   9272  1.1  mrg     {
   9273  1.1  mrg     case BUILT_IN_FILE:
   9274  1.1  mrg       return fold_builtin_FILE (loc);
   9275  1.1  mrg 
   9276  1.1  mrg     case BUILT_IN_FUNCTION:
   9277  1.1  mrg       return fold_builtin_FUNCTION ();
   9278  1.1  mrg 
   9279  1.1  mrg     case BUILT_IN_LINE:
   9280  1.1  mrg       return fold_builtin_LINE (loc, type);
   9281  1.1  mrg 
   9282  1.1  mrg     CASE_FLT_FN (BUILT_IN_INF):
   9283  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
   9284  1.1  mrg     case BUILT_IN_INFD32:
   9285  1.1  mrg     case BUILT_IN_INFD64:
   9286  1.1  mrg     case BUILT_IN_INFD128:
   9287  1.1  mrg       return fold_builtin_inf (loc, type, true);
   9288  1.1  mrg 
   9289  1.1  mrg     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
   9290  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
   9291  1.1  mrg       return fold_builtin_inf (loc, type, false);
   9292  1.1  mrg 
   9293  1.1  mrg     case BUILT_IN_CLASSIFY_TYPE:
   9294  1.1  mrg       return fold_builtin_classify_type (NULL_TREE);
   9295  1.1  mrg 
   9296  1.1  mrg     default:
   9297  1.1  mrg       break;
   9298  1.1  mrg     }
   9299  1.1  mrg   return NULL_TREE;
   9300  1.1  mrg }
   9301  1.1  mrg 
   9302  1.1  mrg /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
   9303  1.1  mrg    This function returns NULL_TREE if no simplification was possible.  */
   9304  1.1  mrg 
   9305  1.1  mrg static tree
   9306  1.1  mrg fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
   9307  1.1  mrg {
   9308  1.1  mrg   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   9309  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   9310  1.1  mrg 
   9311  1.1  mrg   if (TREE_CODE (arg0) == ERROR_MARK)
   9312  1.1  mrg     return NULL_TREE;
   9313  1.1  mrg 
   9314  1.1  mrg   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0))
   9315  1.1  mrg     return ret;
   9316  1.1  mrg 
   9317  1.1  mrg   switch (fcode)
   9318  1.1  mrg     {
   9319  1.1  mrg     case BUILT_IN_CONSTANT_P:
   9320  1.1  mrg       {
   9321  1.1  mrg 	tree val = fold_builtin_constant_p (arg0);
   9322  1.1  mrg 
   9323  1.1  mrg 	/* Gimplification will pull the CALL_EXPR for the builtin out of
   9324  1.1  mrg 	   an if condition.  When not optimizing, we'll not CSE it back.
   9325  1.1  mrg 	   To avoid link error types of regressions, return false now.  */
   9326  1.1  mrg 	if (!val && !optimize)
   9327  1.1  mrg 	  val = integer_zero_node;
   9328  1.1  mrg 
   9329  1.1  mrg 	return val;
   9330  1.1  mrg       }
   9331  1.1  mrg 
   9332  1.1  mrg     case BUILT_IN_CLASSIFY_TYPE:
   9333  1.1  mrg       return fold_builtin_classify_type (arg0);
   9334  1.1  mrg 
   9335  1.1  mrg     case BUILT_IN_STRLEN:
   9336  1.1  mrg       return fold_builtin_strlen (loc, expr, type, arg0);
   9337  1.1  mrg 
   9338  1.1  mrg     CASE_FLT_FN (BUILT_IN_FABS):
   9339  1.1  mrg     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   9340  1.1  mrg     case BUILT_IN_FABSD32:
   9341  1.1  mrg     case BUILT_IN_FABSD64:
   9342  1.1  mrg     case BUILT_IN_FABSD128:
   9343  1.1  mrg       return fold_builtin_fabs (loc, arg0, type);
   9344  1.1  mrg 
   9345  1.1  mrg     case BUILT_IN_ABS:
   9346  1.1  mrg     case BUILT_IN_LABS:
   9347  1.1  mrg     case BUILT_IN_LLABS:
   9348  1.1  mrg     case BUILT_IN_IMAXABS:
   9349  1.1  mrg       return fold_builtin_abs (loc, arg0, type);
   9350  1.1  mrg 
   9351  1.1  mrg     CASE_FLT_FN (BUILT_IN_CONJ):
   9352  1.1  mrg       if (validate_arg (arg0, COMPLEX_TYPE)
   9353  1.1  mrg 	&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   9354  1.1  mrg 	return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
   9355  1.1  mrg     break;
   9356  1.1  mrg 
   9357  1.1  mrg     CASE_FLT_FN (BUILT_IN_CREAL):
   9358  1.1  mrg       if (validate_arg (arg0, COMPLEX_TYPE)
   9359  1.1  mrg 	&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   9360  1.1  mrg 	return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
   9361  1.1  mrg     break;
   9362  1.1  mrg 
   9363  1.1  mrg     CASE_FLT_FN (BUILT_IN_CIMAG):
   9364  1.1  mrg       if (validate_arg (arg0, COMPLEX_TYPE)
   9365  1.1  mrg 	  && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   9366  1.1  mrg 	return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
   9367  1.1  mrg     break;
   9368  1.1  mrg 
   9369  1.1  mrg     CASE_FLT_FN (BUILT_IN_CARG):
   9370  1.1  mrg       return fold_builtin_carg (loc, arg0, type);
   9371  1.1  mrg 
   9372  1.1  mrg     case BUILT_IN_ISASCII:
   9373  1.1  mrg       return fold_builtin_isascii (loc, arg0);
   9374  1.1  mrg 
   9375  1.1  mrg     case BUILT_IN_TOASCII:
   9376  1.1  mrg       return fold_builtin_toascii (loc, arg0);
   9377  1.1  mrg 
   9378  1.1  mrg     case BUILT_IN_ISDIGIT:
   9379  1.1  mrg       return fold_builtin_isdigit (loc, arg0);
   9380  1.1  mrg 
   9381  1.1  mrg     CASE_FLT_FN (BUILT_IN_FINITE):
   9382  1.1  mrg     case BUILT_IN_FINITED32:
   9383  1.1  mrg     case BUILT_IN_FINITED64:
   9384  1.1  mrg     case BUILT_IN_FINITED128:
   9385  1.1  mrg     case BUILT_IN_ISFINITE:
   9386  1.1  mrg       {
   9387  1.1  mrg 	tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
   9388  1.1  mrg 	if (ret)
   9389  1.1  mrg 	  return ret;
   9390  1.1  mrg 	return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   9391  1.1  mrg       }
   9392  1.1  mrg 
   9393  1.1  mrg     CASE_FLT_FN (BUILT_IN_ISINF):
   9394  1.1  mrg     case BUILT_IN_ISINFD32:
   9395  1.1  mrg     case BUILT_IN_ISINFD64:
   9396  1.1  mrg     case BUILT_IN_ISINFD128:
   9397  1.1  mrg       {
   9398  1.1  mrg 	tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
   9399  1.1  mrg 	if (ret)
   9400  1.1  mrg 	  return ret;
   9401  1.1  mrg 	return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   9402  1.1  mrg       }
   9403  1.1  mrg 
   9404  1.1  mrg     case BUILT_IN_ISNORMAL:
   9405  1.1  mrg       return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   9406  1.1  mrg 
   9407  1.1  mrg     case BUILT_IN_ISINF_SIGN:
   9408  1.1  mrg       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
   9409  1.1  mrg 
   9410  1.1  mrg     CASE_FLT_FN (BUILT_IN_ISNAN):
   9411  1.1  mrg     case BUILT_IN_ISNAND32:
   9412  1.1  mrg     case BUILT_IN_ISNAND64:
   9413  1.1  mrg     case BUILT_IN_ISNAND128:
   9414  1.1  mrg       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
   9415  1.1  mrg 
   9416  1.1  mrg     case BUILT_IN_FREE:
   9417  1.1  mrg       if (integer_zerop (arg0))
   9418  1.1  mrg 	return build_empty_stmt (loc);
   9419  1.1  mrg       break;
   9420  1.1  mrg 
   9421  1.1  mrg     default:
   9422  1.1  mrg       break;
   9423  1.1  mrg     }
   9424  1.1  mrg 
   9425  1.1  mrg   return NULL_TREE;
   9426  1.1  mrg 
   9427  1.1  mrg }
   9428  1.1  mrg 
   9429  1.1  mrg /* Folds a call EXPR (which may be null) to built-in function FNDECL
   9430  1.1  mrg    with 2 arguments, ARG0 and ARG1.  This function returns NULL_TREE
   9431  1.1  mrg    if no simplification was possible.  */
   9432  1.1  mrg 
   9433  1.1  mrg static tree
   9434  1.1  mrg fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
   9435  1.1  mrg {
   9436  1.1  mrg   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   9437  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   9438  1.1  mrg 
   9439  1.1  mrg   if (TREE_CODE (arg0) == ERROR_MARK
   9440  1.1  mrg       || TREE_CODE (arg1) == ERROR_MARK)
   9441  1.1  mrg     return NULL_TREE;
   9442  1.1  mrg 
   9443  1.1  mrg   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0, arg1))
   9444  1.1  mrg     return ret;
   9445  1.1  mrg 
   9446  1.1  mrg   switch (fcode)
   9447  1.1  mrg     {
   9448  1.1  mrg     CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
   9449  1.1  mrg     CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
   9450  1.1  mrg       if (validate_arg (arg0, REAL_TYPE)
   9451  1.1  mrg 	  && validate_arg (arg1, POINTER_TYPE))
   9452  1.1  mrg 	return do_mpfr_lgamma_r (arg0, arg1, type);
   9453  1.1  mrg     break;
   9454  1.1  mrg 
   9455  1.1  mrg     CASE_FLT_FN (BUILT_IN_FREXP):
   9456  1.1  mrg       return fold_builtin_frexp (loc, arg0, arg1, type);
   9457  1.1  mrg 
   9458  1.1  mrg     CASE_FLT_FN (BUILT_IN_MODF):
   9459  1.1  mrg       return fold_builtin_modf (loc, arg0, arg1, type);
   9460  1.1  mrg 
   9461  1.1  mrg     case BUILT_IN_STRSPN:
   9462  1.1  mrg       return fold_builtin_strspn (loc, expr, arg0, arg1);
   9463  1.1  mrg 
   9464  1.1  mrg     case BUILT_IN_STRCSPN:
   9465  1.1  mrg       return fold_builtin_strcspn (loc, expr, arg0, arg1);
   9466  1.1  mrg 
   9467  1.1  mrg     case BUILT_IN_STRPBRK:
   9468  1.1  mrg       return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
   9469  1.1  mrg 
   9470  1.1  mrg     case BUILT_IN_EXPECT:
   9471  1.1  mrg       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
   9472  1.1  mrg 
   9473  1.1  mrg     case BUILT_IN_ISGREATER:
   9474  1.1  mrg       return fold_builtin_unordered_cmp (loc, fndecl,
   9475  1.1  mrg 					 arg0, arg1, UNLE_EXPR, LE_EXPR);
   9476  1.1  mrg     case BUILT_IN_ISGREATEREQUAL:
   9477  1.1  mrg       return fold_builtin_unordered_cmp (loc, fndecl,
   9478  1.1  mrg 					 arg0, arg1, UNLT_EXPR, LT_EXPR);
   9479  1.1  mrg     case BUILT_IN_ISLESS:
   9480  1.1  mrg       return fold_builtin_unordered_cmp (loc, fndecl,
   9481  1.1  mrg 					 arg0, arg1, UNGE_EXPR, GE_EXPR);
   9482  1.1  mrg     case BUILT_IN_ISLESSEQUAL:
   9483  1.1  mrg       return fold_builtin_unordered_cmp (loc, fndecl,
   9484  1.1  mrg 					 arg0, arg1, UNGT_EXPR, GT_EXPR);
   9485  1.1  mrg     case BUILT_IN_ISLESSGREATER:
   9486  1.1  mrg       return fold_builtin_unordered_cmp (loc, fndecl,
   9487  1.1  mrg 					 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
   9488  1.1  mrg     case BUILT_IN_ISUNORDERED:
   9489  1.1  mrg       return fold_builtin_unordered_cmp (loc, fndecl,
   9490  1.1  mrg 					 arg0, arg1, UNORDERED_EXPR,
   9491  1.1  mrg 					 NOP_EXPR);
   9492  1.1  mrg 
   9493  1.1  mrg       /* We do the folding for va_start in the expander.  */
   9494  1.1  mrg     case BUILT_IN_VA_START:
   9495  1.1  mrg       break;
   9496  1.1  mrg 
   9497  1.1  mrg     case BUILT_IN_OBJECT_SIZE:
   9498  1.1  mrg     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
   9499  1.1  mrg       return fold_builtin_object_size (arg0, arg1, fcode);
   9500  1.1  mrg 
   9501  1.1  mrg     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
   9502  1.1  mrg       return fold_builtin_atomic_always_lock_free (arg0, arg1);
   9503  1.1  mrg 
   9504  1.1  mrg     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
   9505  1.1  mrg       return fold_builtin_atomic_is_lock_free (arg0, arg1);
   9506  1.1  mrg 
   9507  1.1  mrg     default:
   9508  1.1  mrg       break;
   9509  1.1  mrg     }
   9510  1.1  mrg   return NULL_TREE;
   9511  1.1  mrg }
   9512  1.1  mrg 
   9513  1.1  mrg /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
   9514  1.1  mrg    and ARG2.
   9515  1.1  mrg    This function returns NULL_TREE if no simplification was possible.  */
   9516  1.1  mrg 
   9517  1.1  mrg static tree
   9518  1.1  mrg fold_builtin_3 (location_t loc, tree fndecl,
   9519  1.1  mrg 		tree arg0, tree arg1, tree arg2)
   9520  1.1  mrg {
   9521  1.1  mrg   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   9522  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   9523  1.1  mrg 
   9524  1.1  mrg   if (TREE_CODE (arg0) == ERROR_MARK
   9525  1.1  mrg       || TREE_CODE (arg1) == ERROR_MARK
   9526  1.1  mrg       || TREE_CODE (arg2) == ERROR_MARK)
   9527  1.1  mrg     return NULL_TREE;
   9528  1.1  mrg 
   9529  1.1  mrg   if (tree ret = fold_const_call (as_combined_fn (fcode), type,
   9530  1.1  mrg 				  arg0, arg1, arg2))
   9531  1.1  mrg     return ret;
   9532  1.1  mrg 
   9533  1.1  mrg   switch (fcode)
   9534  1.1  mrg     {
   9535  1.1  mrg 
   9536  1.1  mrg     CASE_FLT_FN (BUILT_IN_SINCOS):
   9537  1.1  mrg       return fold_builtin_sincos (loc, arg0, arg1, arg2);
   9538  1.1  mrg 
   9539  1.1  mrg     CASE_FLT_FN (BUILT_IN_REMQUO):
   9540  1.1  mrg       if (validate_arg (arg0, REAL_TYPE)
   9541  1.1  mrg 	  && validate_arg (arg1, REAL_TYPE)
   9542  1.1  mrg 	  && validate_arg (arg2, POINTER_TYPE))
   9543  1.1  mrg 	return do_mpfr_remquo (arg0, arg1, arg2);
   9544  1.1  mrg     break;
   9545  1.1  mrg 
   9546  1.1  mrg     case BUILT_IN_MEMCMP:
   9547  1.1  mrg       return fold_builtin_memcmp (loc, arg0, arg1, arg2);
   9548  1.1  mrg 
   9549  1.1  mrg     case BUILT_IN_EXPECT:
   9550  1.1  mrg       return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
   9551  1.1  mrg 
   9552  1.1  mrg     case BUILT_IN_EXPECT_WITH_PROBABILITY:
   9553  1.1  mrg       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
   9554  1.1  mrg 
   9555  1.1  mrg     case BUILT_IN_ADD_OVERFLOW:
   9556  1.1  mrg     case BUILT_IN_SUB_OVERFLOW:
   9557  1.1  mrg     case BUILT_IN_MUL_OVERFLOW:
   9558  1.1  mrg     case BUILT_IN_ADD_OVERFLOW_P:
   9559  1.1  mrg     case BUILT_IN_SUB_OVERFLOW_P:
   9560  1.1  mrg     case BUILT_IN_MUL_OVERFLOW_P:
   9561  1.1  mrg     case BUILT_IN_SADD_OVERFLOW:
   9562  1.1  mrg     case BUILT_IN_SADDL_OVERFLOW:
   9563  1.1  mrg     case BUILT_IN_SADDLL_OVERFLOW:
   9564  1.1  mrg     case BUILT_IN_SSUB_OVERFLOW:
   9565  1.1  mrg     case BUILT_IN_SSUBL_OVERFLOW:
   9566  1.1  mrg     case BUILT_IN_SSUBLL_OVERFLOW:
   9567  1.1  mrg     case BUILT_IN_SMUL_OVERFLOW:
   9568  1.1  mrg     case BUILT_IN_SMULL_OVERFLOW:
   9569  1.1  mrg     case BUILT_IN_SMULLL_OVERFLOW:
   9570  1.1  mrg     case BUILT_IN_UADD_OVERFLOW:
   9571  1.1  mrg     case BUILT_IN_UADDL_OVERFLOW:
   9572  1.1  mrg     case BUILT_IN_UADDLL_OVERFLOW:
   9573  1.1  mrg     case BUILT_IN_USUB_OVERFLOW:
   9574  1.1  mrg     case BUILT_IN_USUBL_OVERFLOW:
   9575  1.1  mrg     case BUILT_IN_USUBLL_OVERFLOW:
   9576  1.1  mrg     case BUILT_IN_UMUL_OVERFLOW:
   9577  1.1  mrg     case BUILT_IN_UMULL_OVERFLOW:
   9578  1.1  mrg     case BUILT_IN_UMULLL_OVERFLOW:
   9579  1.1  mrg       return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
   9580  1.1  mrg 
   9581  1.1  mrg     default:
   9582  1.1  mrg       break;
   9583  1.1  mrg     }
   9584  1.1  mrg   return NULL_TREE;
   9585  1.1  mrg }
   9586  1.1  mrg 
   9587  1.1  mrg /* Folds a call EXPR (which may be null) to built-in function FNDECL.
   9588  1.1  mrg    ARGS is an array of NARGS arguments.  IGNORE is true if the result
   9589  1.1  mrg    of the function call is ignored.  This function returns NULL_TREE
   9590  1.1  mrg    if no simplification was possible.  */
   9591  1.1  mrg 
   9592  1.1  mrg static tree
   9593  1.1  mrg fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
   9594  1.1  mrg 		int nargs, bool)
   9595  1.1  mrg {
   9596  1.1  mrg   tree ret = NULL_TREE;
   9597  1.1  mrg 
   9598  1.1  mrg   switch (nargs)
   9599  1.1  mrg     {
   9600  1.1  mrg     case 0:
   9601  1.1  mrg       ret = fold_builtin_0 (loc, fndecl);
   9602  1.1  mrg       break;
   9603  1.1  mrg     case 1:
   9604  1.1  mrg       ret = fold_builtin_1 (loc, expr, fndecl, args[0]);
   9605  1.1  mrg       break;
   9606  1.1  mrg     case 2:
   9607  1.1  mrg       ret = fold_builtin_2 (loc, expr, fndecl, args[0], args[1]);
   9608  1.1  mrg       break;
   9609  1.1  mrg     case 3:
   9610  1.1  mrg       ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
   9611  1.1  mrg       break;
   9612  1.1  mrg     default:
   9613  1.1  mrg       ret = fold_builtin_varargs (loc, fndecl, args, nargs);
   9614  1.1  mrg       break;
   9615  1.1  mrg     }
   9616  1.1  mrg   if (ret)
   9617  1.1  mrg     {
   9618  1.1  mrg       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   9619  1.1  mrg       SET_EXPR_LOCATION (ret, loc);
   9620  1.1  mrg       return ret;
   9621  1.1  mrg     }
   9622  1.1  mrg   return NULL_TREE;
   9623  1.1  mrg }
   9624  1.1  mrg 
   9625  1.1  mrg /* Construct a new CALL_EXPR to FNDECL using the tail of the argument
   9626  1.1  mrg    list ARGS along with N new arguments in NEWARGS.  SKIP is the number
   9627  1.1  mrg    of arguments in ARGS to be omitted.  OLDNARGS is the number of
   9628  1.1  mrg    elements in ARGS.  */
   9629  1.1  mrg 
   9630  1.1  mrg static tree
   9631  1.1  mrg rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
   9632  1.1  mrg 			  int skip, tree fndecl, int n, va_list newargs)
   9633  1.1  mrg {
   9634  1.1  mrg   int nargs = oldnargs - skip + n;
   9635  1.1  mrg   tree *buffer;
   9636  1.1  mrg 
   9637  1.1  mrg   if (n > 0)
   9638  1.1  mrg     {
   9639  1.1  mrg       int i, j;
   9640  1.1  mrg 
   9641  1.1  mrg       buffer = XALLOCAVEC (tree, nargs);
   9642  1.1  mrg       for (i = 0; i < n; i++)
   9643  1.1  mrg 	buffer[i] = va_arg (newargs, tree);
   9644  1.1  mrg       for (j = skip; j < oldnargs; j++, i++)
   9645  1.1  mrg 	buffer[i] = args[j];
   9646  1.1  mrg     }
   9647  1.1  mrg   else
   9648  1.1  mrg     buffer = args + skip;
   9649  1.1  mrg 
   9650  1.1  mrg   return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
   9651  1.1  mrg }
   9652  1.1  mrg 
   9653  1.1  mrg /* Return true if FNDECL shouldn't be folded right now.
   9654  1.1  mrg    If a built-in function has an inline attribute always_inline
   9655  1.1  mrg    wrapper, defer folding it after always_inline functions have
   9656  1.1  mrg    been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
   9657  1.1  mrg    might not be performed.  */
   9658  1.1  mrg 
   9659  1.1  mrg bool
   9660  1.1  mrg avoid_folding_inline_builtin (tree fndecl)
   9661  1.1  mrg {
   9662  1.1  mrg   return (DECL_DECLARED_INLINE_P (fndecl)
   9663  1.1  mrg 	  && DECL_DISREGARD_INLINE_LIMITS (fndecl)
   9664  1.1  mrg 	  && cfun
   9665  1.1  mrg 	  && !cfun->always_inline_functions_inlined
   9666  1.1  mrg 	  && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
   9667  1.1  mrg }
   9668  1.1  mrg 
   9669  1.1  mrg /* A wrapper function for builtin folding that prevents warnings for
   9670  1.1  mrg    "statement without effect" and the like, caused by removing the
   9671  1.1  mrg    call node earlier than the warning is generated.  */
   9672  1.1  mrg 
   9673  1.1  mrg tree
   9674  1.1  mrg fold_call_expr (location_t loc, tree exp, bool ignore)
   9675  1.1  mrg {
   9676  1.1  mrg   tree ret = NULL_TREE;
   9677  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   9678  1.1  mrg   if (fndecl && fndecl_built_in_p (fndecl)
   9679  1.1  mrg       /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
   9680  1.1  mrg 	 yet.  Defer folding until we see all the arguments
   9681  1.1  mrg 	 (after inlining).  */
   9682  1.1  mrg       && !CALL_EXPR_VA_ARG_PACK (exp))
   9683  1.1  mrg     {
   9684  1.1  mrg       int nargs = call_expr_nargs (exp);
   9685  1.1  mrg 
   9686  1.1  mrg       /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
   9687  1.1  mrg 	 instead last argument is __builtin_va_arg_pack ().  Defer folding
   9688  1.1  mrg 	 even in that case, until arguments are finalized.  */
   9689  1.1  mrg       if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
   9690  1.1  mrg 	{
   9691  1.1  mrg 	  tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
   9692  1.1  mrg 	  if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   9693  1.1  mrg 	    return NULL_TREE;
   9694  1.1  mrg 	}
   9695  1.1  mrg 
   9696  1.1  mrg       if (avoid_folding_inline_builtin (fndecl))
   9697  1.1  mrg 	return NULL_TREE;
   9698  1.1  mrg 
   9699  1.1  mrg       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   9700  1.1  mrg         return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
   9701  1.1  mrg 				     CALL_EXPR_ARGP (exp), ignore);
   9702  1.1  mrg       else
   9703  1.1  mrg 	{
   9704  1.1  mrg 	  tree *args = CALL_EXPR_ARGP (exp);
   9705  1.1  mrg 	  ret = fold_builtin_n (loc, exp, fndecl, args, nargs, ignore);
   9706  1.1  mrg 	  if (ret)
   9707  1.1  mrg 	    return ret;
   9708  1.1  mrg 	}
   9709  1.1  mrg     }
   9710  1.1  mrg   return NULL_TREE;
   9711  1.1  mrg }
   9712  1.1  mrg 
   9713  1.1  mrg /* Fold a CALL_EXPR with type TYPE with FN as the function expression.
   9714  1.1  mrg    N arguments are passed in the array ARGARRAY.  Return a folded
   9715  1.1  mrg    expression or NULL_TREE if no simplification was possible.  */
   9716  1.1  mrg 
   9717  1.1  mrg tree
   9718  1.1  mrg fold_builtin_call_array (location_t loc, tree,
   9719  1.1  mrg 			 tree fn,
   9720  1.1  mrg 			 int n,
   9721  1.1  mrg 			 tree *argarray)
   9722  1.1  mrg {
   9723  1.1  mrg   if (TREE_CODE (fn) != ADDR_EXPR)
   9724  1.1  mrg     return NULL_TREE;
   9725  1.1  mrg 
   9726  1.1  mrg   tree fndecl = TREE_OPERAND (fn, 0);
   9727  1.1  mrg   if (TREE_CODE (fndecl) == FUNCTION_DECL
   9728  1.1  mrg       && fndecl_built_in_p (fndecl))
   9729  1.1  mrg     {
   9730  1.1  mrg       /* If last argument is __builtin_va_arg_pack (), arguments to this
   9731  1.1  mrg 	 function are not finalized yet.  Defer folding until they are.  */
   9732  1.1  mrg       if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
   9733  1.1  mrg 	{
   9734  1.1  mrg 	  tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
   9735  1.1  mrg 	  if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   9736  1.1  mrg 	    return NULL_TREE;
   9737  1.1  mrg 	}
   9738  1.1  mrg       if (avoid_folding_inline_builtin (fndecl))
   9739  1.1  mrg 	return NULL_TREE;
   9740  1.1  mrg       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   9741  1.1  mrg 	return targetm.fold_builtin (fndecl, n, argarray, false);
   9742  1.1  mrg       else
   9743  1.1  mrg 	return fold_builtin_n (loc, NULL_TREE, fndecl, argarray, n, false);
   9744  1.1  mrg     }
   9745  1.1  mrg 
   9746  1.1  mrg   return NULL_TREE;
   9747  1.1  mrg }
   9748  1.1  mrg 
   9749  1.1  mrg /* Construct a new CALL_EXPR using the tail of the argument list of EXP
   9750  1.1  mrg    along with N new arguments specified as the "..." parameters.  SKIP
   9751  1.1  mrg    is the number of arguments in EXP to be omitted.  This function is used
   9752  1.1  mrg    to do varargs-to-varargs transformations.  */
   9753  1.1  mrg 
   9754  1.1  mrg static tree
   9755  1.1  mrg rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
   9756  1.1  mrg {
   9757  1.1  mrg   va_list ap;
   9758  1.1  mrg   tree t;
   9759  1.1  mrg 
   9760  1.1  mrg   va_start (ap, n);
   9761  1.1  mrg   t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
   9762  1.1  mrg 				CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
   9763  1.1  mrg   va_end (ap);
   9764  1.1  mrg 
   9765  1.1  mrg   return t;
   9766  1.1  mrg }
   9767  1.1  mrg 
   9768  1.1  mrg /* Validate a single argument ARG against a tree code CODE representing
   9769  1.1  mrg    a type.  Return true when argument is valid.  */
   9770  1.1  mrg 
   9771  1.1  mrg static bool
   9772  1.1  mrg validate_arg (const_tree arg, enum tree_code code)
   9773  1.1  mrg {
   9774  1.1  mrg   if (!arg)
   9775  1.1  mrg     return false;
   9776  1.1  mrg   else if (code == POINTER_TYPE)
   9777  1.1  mrg     return POINTER_TYPE_P (TREE_TYPE (arg));
   9778  1.1  mrg   else if (code == INTEGER_TYPE)
   9779  1.1  mrg     return INTEGRAL_TYPE_P (TREE_TYPE (arg));
   9780  1.1  mrg   return code == TREE_CODE (TREE_TYPE (arg));
   9781  1.1  mrg }
   9782  1.1  mrg 
   9783  1.1  mrg /* This function validates the types of a function call argument list
   9784  1.1  mrg    against a specified list of tree_codes.  If the last specifier is a 0,
   9785  1.1  mrg    that represents an ellipses, otherwise the last specifier must be a
   9786  1.1  mrg    VOID_TYPE.
   9787  1.1  mrg 
   9788  1.1  mrg    This is the GIMPLE version of validate_arglist.  Eventually we want to
   9789  1.1  mrg    completely convert builtins.cc to work from GIMPLEs and the tree based
   9790  1.1  mrg    validate_arglist will then be removed.  */
   9791  1.1  mrg 
   9792  1.1  mrg bool
   9793  1.1  mrg validate_gimple_arglist (const gcall *call, ...)
   9794  1.1  mrg {
   9795  1.1  mrg   enum tree_code code;
   9796  1.1  mrg   bool res = 0;
   9797  1.1  mrg   va_list ap;
   9798  1.1  mrg   const_tree arg;
   9799  1.1  mrg   size_t i;
   9800  1.1  mrg 
   9801  1.1  mrg   va_start (ap, call);
   9802  1.1  mrg   i = 0;
   9803  1.1  mrg 
   9804  1.1  mrg   do
   9805  1.1  mrg     {
   9806  1.1  mrg       code = (enum tree_code) va_arg (ap, int);
   9807  1.1  mrg       switch (code)
   9808  1.1  mrg 	{
   9809  1.1  mrg 	case 0:
   9810  1.1  mrg 	  /* This signifies an ellipses, any further arguments are all ok.  */
   9811  1.1  mrg 	  res = true;
   9812  1.1  mrg 	  goto end;
   9813  1.1  mrg 	case VOID_TYPE:
   9814  1.1  mrg 	  /* This signifies an endlink, if no arguments remain, return
   9815  1.1  mrg 	     true, otherwise return false.  */
   9816  1.1  mrg 	  res = (i == gimple_call_num_args (call));
   9817  1.1  mrg 	  goto end;
   9818  1.1  mrg 	default:
   9819  1.1  mrg 	  /* If no parameters remain or the parameter's code does not
   9820  1.1  mrg 	     match the specified code, return false.  Otherwise continue
   9821  1.1  mrg 	     checking any remaining arguments.  */
   9822  1.1  mrg 	  arg = gimple_call_arg (call, i++);
   9823  1.1  mrg 	  if (!validate_arg (arg, code))
   9824  1.1  mrg 	    goto end;
   9825  1.1  mrg 	  break;
   9826  1.1  mrg 	}
   9827  1.1  mrg     }
   9828  1.1  mrg   while (1);
   9829  1.1  mrg 
   9830  1.1  mrg   /* We need gotos here since we can only have one VA_CLOSE in a
   9831  1.1  mrg      function.  */
   9832  1.1  mrg  end: ;
   9833  1.1  mrg   va_end (ap);
   9834  1.1  mrg 
   9835  1.1  mrg   return res;
   9836  1.1  mrg }
   9837  1.1  mrg 
   9838  1.1  mrg /* Default target-specific builtin expander that does nothing.  */
   9839  1.1  mrg 
   9840  1.1  mrg rtx
   9841  1.1  mrg default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
   9842  1.1  mrg 			rtx target ATTRIBUTE_UNUSED,
   9843  1.1  mrg 			rtx subtarget ATTRIBUTE_UNUSED,
   9844  1.1  mrg 			machine_mode mode ATTRIBUTE_UNUSED,
   9845  1.1  mrg 			int ignore ATTRIBUTE_UNUSED)
   9846  1.1  mrg {
   9847  1.1  mrg   return NULL_RTX;
   9848  1.1  mrg }
   9849  1.1  mrg 
   9850  1.1  mrg /* Returns true is EXP represents data that would potentially reside
   9851  1.1  mrg    in a readonly section.  */
   9852  1.1  mrg 
   9853  1.1  mrg bool
   9854  1.1  mrg readonly_data_expr (tree exp)
   9855  1.1  mrg {
   9856  1.1  mrg   STRIP_NOPS (exp);
   9857  1.1  mrg 
   9858  1.1  mrg   if (TREE_CODE (exp) != ADDR_EXPR)
   9859  1.1  mrg     return false;
   9860  1.1  mrg 
   9861  1.1  mrg   exp = get_base_address (TREE_OPERAND (exp, 0));
   9862  1.1  mrg   if (!exp)
   9863  1.1  mrg     return false;
   9864  1.1  mrg 
   9865  1.1  mrg   /* Make sure we call decl_readonly_section only for trees it
   9866  1.1  mrg      can handle (since it returns true for everything it doesn't
   9867  1.1  mrg      understand).  */
   9868  1.1  mrg   if (TREE_CODE (exp) == STRING_CST
   9869  1.1  mrg       || TREE_CODE (exp) == CONSTRUCTOR
   9870  1.1  mrg       || (VAR_P (exp) && TREE_STATIC (exp)))
   9871  1.1  mrg     return decl_readonly_section (exp, 0);
   9872  1.1  mrg   else
   9873  1.1  mrg     return false;
   9874  1.1  mrg }
   9875  1.1  mrg 
   9876  1.1  mrg /* Simplify a call to the strpbrk builtin.  S1 and S2 are the arguments
   9877  1.1  mrg    to the call, and TYPE is its return type.
   9878  1.1  mrg 
   9879  1.1  mrg    Return NULL_TREE if no simplification was possible, otherwise return the
   9880  1.1  mrg    simplified form of the call as a tree.
   9881  1.1  mrg 
   9882  1.1  mrg    The simplified form may be a constant or other expression which
   9883  1.1  mrg    computes the same value, but in a more efficient manner (including
   9884  1.1  mrg    calls to other builtin functions).
   9885  1.1  mrg 
   9886  1.1  mrg    The call may contain arguments which need to be evaluated, but
   9887  1.1  mrg    which are not useful to determine the result of the call.  In
   9888  1.1  mrg    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   9889  1.1  mrg    COMPOUND_EXPR will be an argument which must be evaluated.
   9890  1.1  mrg    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   9891  1.1  mrg    COMPOUND_EXPR in the chain will contain the tree for the simplified
   9892  1.1  mrg    form of the builtin function call.  */
   9893  1.1  mrg 
   9894  1.1  mrg static tree
   9895  1.1  mrg fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
   9896  1.1  mrg {
   9897  1.1  mrg   if (!validate_arg (s1, POINTER_TYPE)
   9898  1.1  mrg       || !validate_arg (s2, POINTER_TYPE))
   9899  1.1  mrg     return NULL_TREE;
   9900  1.1  mrg 
   9901  1.1  mrg   tree fn;
   9902  1.1  mrg   const char *p1, *p2;
   9903  1.1  mrg 
   9904  1.1  mrg   p2 = c_getstr (s2);
   9905  1.1  mrg   if (p2 == NULL)
   9906  1.1  mrg     return NULL_TREE;
   9907  1.1  mrg 
   9908  1.1  mrg   p1 = c_getstr (s1);
   9909  1.1  mrg   if (p1 != NULL)
   9910  1.1  mrg     {
   9911  1.1  mrg       const char *r = strpbrk (p1, p2);
   9912  1.1  mrg       tree tem;
   9913  1.1  mrg 
   9914  1.1  mrg       if (r == NULL)
   9915  1.1  mrg 	return build_int_cst (TREE_TYPE (s1), 0);
   9916  1.1  mrg 
   9917  1.1  mrg       /* Return an offset into the constant string argument.  */
   9918  1.1  mrg       tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
   9919  1.1  mrg       return fold_convert_loc (loc, type, tem);
   9920  1.1  mrg     }
   9921  1.1  mrg 
   9922  1.1  mrg   if (p2[0] == '\0')
   9923  1.1  mrg     /* strpbrk(x, "") == NULL.
   9924  1.1  mrg        Evaluate and ignore s1 in case it had side-effects.  */
   9925  1.1  mrg     return omit_one_operand_loc (loc, type, integer_zero_node, s1);
   9926  1.1  mrg 
   9927  1.1  mrg   if (p2[1] != '\0')
   9928  1.1  mrg     return NULL_TREE;  /* Really call strpbrk.  */
   9929  1.1  mrg 
   9930  1.1  mrg   fn = builtin_decl_implicit (BUILT_IN_STRCHR);
   9931  1.1  mrg   if (!fn)
   9932  1.1  mrg     return NULL_TREE;
   9933  1.1  mrg 
   9934  1.1  mrg   /* New argument list transforming strpbrk(s1, s2) to
   9935  1.1  mrg      strchr(s1, s2[0]).  */
   9936  1.1  mrg   return build_call_expr_loc (loc, fn, 2, s1,
   9937  1.1  mrg 			      build_int_cst (integer_type_node, p2[0]));
   9938  1.1  mrg }
   9939  1.1  mrg 
   9940  1.1  mrg /* Simplify a call to the strspn builtin.  S1 and S2 are the arguments
   9941  1.1  mrg    to the call.
   9942  1.1  mrg 
   9943  1.1  mrg    Return NULL_TREE if no simplification was possible, otherwise return the
   9944  1.1  mrg    simplified form of the call as a tree.
   9945  1.1  mrg 
   9946  1.1  mrg    The simplified form may be a constant or other expression which
   9947  1.1  mrg    computes the same value, but in a more efficient manner (including
   9948  1.1  mrg    calls to other builtin functions).
   9949  1.1  mrg 
   9950  1.1  mrg    The call may contain arguments which need to be evaluated, but
   9951  1.1  mrg    which are not useful to determine the result of the call.  In
   9952  1.1  mrg    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   9953  1.1  mrg    COMPOUND_EXPR will be an argument which must be evaluated.
   9954  1.1  mrg    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   9955  1.1  mrg    COMPOUND_EXPR in the chain will contain the tree for the simplified
   9956  1.1  mrg    form of the builtin function call.  */
   9957  1.1  mrg 
   9958  1.1  mrg static tree
   9959  1.1  mrg fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2)
   9960  1.1  mrg {
   9961  1.1  mrg   if (!validate_arg (s1, POINTER_TYPE)
   9962  1.1  mrg       || !validate_arg (s2, POINTER_TYPE))
   9963  1.1  mrg     return NULL_TREE;
   9964  1.1  mrg 
   9965  1.1  mrg   if (!check_nul_terminated_array (expr, s1)
   9966  1.1  mrg       || !check_nul_terminated_array (expr, s2))
   9967  1.1  mrg     return NULL_TREE;
   9968  1.1  mrg 
   9969  1.1  mrg   const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
   9970  1.1  mrg 
   9971  1.1  mrg   /* If either argument is "", return NULL_TREE.  */
   9972  1.1  mrg   if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
   9973  1.1  mrg     /* Evaluate and ignore both arguments in case either one has
   9974  1.1  mrg        side-effects.  */
   9975  1.1  mrg     return omit_two_operands_loc (loc, size_type_node, size_zero_node,
   9976  1.1  mrg 				  s1, s2);
   9977  1.1  mrg   return NULL_TREE;
   9978  1.1  mrg }
   9979  1.1  mrg 
   9980  1.1  mrg /* Simplify a call to the strcspn builtin.  S1 and S2 are the arguments
   9981  1.1  mrg    to the call.
   9982  1.1  mrg 
   9983  1.1  mrg    Return NULL_TREE if no simplification was possible, otherwise return the
   9984  1.1  mrg    simplified form of the call as a tree.
   9985  1.1  mrg 
   9986  1.1  mrg    The simplified form may be a constant or other expression which
   9987  1.1  mrg    computes the same value, but in a more efficient manner (including
   9988  1.1  mrg    calls to other builtin functions).
   9989  1.1  mrg 
   9990  1.1  mrg    The call may contain arguments which need to be evaluated, but
   9991  1.1  mrg    which are not useful to determine the result of the call.  In
   9992  1.1  mrg    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   9993  1.1  mrg    COMPOUND_EXPR will be an argument which must be evaluated.
   9994  1.1  mrg    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   9995  1.1  mrg    COMPOUND_EXPR in the chain will contain the tree for the simplified
   9996  1.1  mrg    form of the builtin function call.  */
   9997  1.1  mrg 
   9998  1.1  mrg static tree
   9999  1.1  mrg fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2)
   10000  1.1  mrg {
   10001  1.1  mrg   if (!validate_arg (s1, POINTER_TYPE)
   10002  1.1  mrg       || !validate_arg (s2, POINTER_TYPE))
   10003  1.1  mrg     return NULL_TREE;
   10004  1.1  mrg 
   10005  1.1  mrg   if (!check_nul_terminated_array (expr, s1)
   10006  1.1  mrg       || !check_nul_terminated_array (expr, s2))
   10007  1.1  mrg     return NULL_TREE;
   10008  1.1  mrg 
   10009  1.1  mrg   /* If the first argument is "", return NULL_TREE.  */
   10010  1.1  mrg   const char *p1 = c_getstr (s1);
   10011  1.1  mrg   if (p1 && *p1 == '\0')
   10012  1.1  mrg     {
   10013  1.1  mrg       /* Evaluate and ignore argument s2 in case it has
   10014  1.1  mrg 	 side-effects.  */
   10015  1.1  mrg       return omit_one_operand_loc (loc, size_type_node,
   10016  1.1  mrg 				   size_zero_node, s2);
   10017  1.1  mrg     }
   10018  1.1  mrg 
   10019  1.1  mrg   /* If the second argument is "", return __builtin_strlen(s1).  */
   10020  1.1  mrg   const char *p2 = c_getstr (s2);
   10021  1.1  mrg   if (p2 && *p2 == '\0')
   10022  1.1  mrg     {
   10023  1.1  mrg       tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
   10024  1.1  mrg 
   10025  1.1  mrg       /* If the replacement _DECL isn't initialized, don't do the
   10026  1.1  mrg 	 transformation.  */
   10027  1.1  mrg       if (!fn)
   10028  1.1  mrg 	return NULL_TREE;
   10029  1.1  mrg 
   10030  1.1  mrg       return build_call_expr_loc (loc, fn, 1, s1);
   10031  1.1  mrg     }
   10032  1.1  mrg   return NULL_TREE;
   10033  1.1  mrg }
   10034  1.1  mrg 
   10035  1.1  mrg /* Fold the next_arg or va_start call EXP. Returns true if there was an error
   10036  1.1  mrg    produced.  False otherwise.  This is done so that we don't output the error
   10037  1.1  mrg    or warning twice or three times.  */
   10038  1.1  mrg 
   10039  1.1  mrg bool
   10040  1.1  mrg fold_builtin_next_arg (tree exp, bool va_start_p)
   10041  1.1  mrg {
   10042  1.1  mrg   tree fntype = TREE_TYPE (current_function_decl);
   10043  1.1  mrg   int nargs = call_expr_nargs (exp);
   10044  1.1  mrg   tree arg;
   10045  1.1  mrg   /* There is good chance the current input_location points inside the
   10046  1.1  mrg      definition of the va_start macro (perhaps on the token for
   10047  1.1  mrg      builtin) in a system header, so warnings will not be emitted.
   10048  1.1  mrg      Use the location in real source code.  */
   10049  1.1  mrg   location_t current_location =
   10050  1.1  mrg     linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
   10051  1.1  mrg 					      NULL);
   10052  1.1  mrg 
   10053  1.1  mrg   if (!stdarg_p (fntype))
   10054  1.1  mrg     {
   10055  1.1  mrg       error ("%<va_start%> used in function with fixed arguments");
   10056  1.1  mrg       return true;
   10057  1.1  mrg     }
   10058  1.1  mrg 
   10059  1.1  mrg   if (va_start_p)
   10060  1.1  mrg     {
   10061  1.1  mrg       if (va_start_p && (nargs != 2))
   10062  1.1  mrg 	{
   10063  1.1  mrg 	  error ("wrong number of arguments to function %<va_start%>");
   10064  1.1  mrg 	  return true;
   10065  1.1  mrg 	}
   10066  1.1  mrg       arg = CALL_EXPR_ARG (exp, 1);
   10067  1.1  mrg     }
   10068  1.1  mrg   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
   10069  1.1  mrg      when we checked the arguments and if needed issued a warning.  */
   10070  1.1  mrg   else
   10071  1.1  mrg     {
   10072  1.1  mrg       if (nargs == 0)
   10073  1.1  mrg 	{
   10074  1.1  mrg 	  /* Evidently an out of date version of <stdarg.h>; can't validate
   10075  1.1  mrg 	     va_start's second argument, but can still work as intended.  */
   10076  1.1  mrg 	  warning_at (current_location,
   10077  1.1  mrg 		      OPT_Wvarargs,
   10078  1.1  mrg 		   "%<__builtin_next_arg%> called without an argument");
   10079  1.1  mrg 	  return true;
   10080  1.1  mrg 	}
   10081  1.1  mrg       else if (nargs > 1)
   10082  1.1  mrg 	{
   10083  1.1  mrg 	  error ("wrong number of arguments to function %<__builtin_next_arg%>");
   10084  1.1  mrg 	  return true;
   10085  1.1  mrg 	}
   10086  1.1  mrg       arg = CALL_EXPR_ARG (exp, 0);
   10087  1.1  mrg     }
   10088  1.1  mrg 
   10089  1.1  mrg   if (TREE_CODE (arg) == SSA_NAME
   10090  1.1  mrg       && SSA_NAME_VAR (arg))
   10091  1.1  mrg     arg = SSA_NAME_VAR (arg);
   10092  1.1  mrg 
   10093  1.1  mrg   /* We destructively modify the call to be __builtin_va_start (ap, 0)
   10094  1.1  mrg      or __builtin_next_arg (0) the first time we see it, after checking
   10095  1.1  mrg      the arguments and if needed issuing a warning.  */
   10096  1.1  mrg   if (!integer_zerop (arg))
   10097  1.1  mrg     {
   10098  1.1  mrg       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
   10099  1.1  mrg 
   10100  1.1  mrg       /* Strip off all nops for the sake of the comparison.  This
   10101  1.1  mrg 	 is not quite the same as STRIP_NOPS.  It does more.
   10102  1.1  mrg 	 We must also strip off INDIRECT_EXPR for C++ reference
   10103  1.1  mrg 	 parameters.  */
   10104  1.1  mrg       while (CONVERT_EXPR_P (arg)
   10105  1.1  mrg 	     || TREE_CODE (arg) == INDIRECT_REF)
   10106  1.1  mrg 	arg = TREE_OPERAND (arg, 0);
   10107  1.1  mrg       if (arg != last_parm)
   10108  1.1  mrg 	{
   10109  1.1  mrg 	  /* FIXME: Sometimes with the tree optimizers we can get the
   10110  1.1  mrg 	     not the last argument even though the user used the last
   10111  1.1  mrg 	     argument.  We just warn and set the arg to be the last
   10112  1.1  mrg 	     argument so that we will get wrong-code because of
   10113  1.1  mrg 	     it.  */
   10114  1.1  mrg 	  warning_at (current_location,
   10115  1.1  mrg 		      OPT_Wvarargs,
   10116  1.1  mrg 		      "second parameter of %<va_start%> not last named argument");
   10117  1.1  mrg 	}
   10118  1.1  mrg 
   10119  1.1  mrg       /* Undefined by C99 7.15.1.4p4 (va_start):
   10120  1.1  mrg          "If the parameter parmN is declared with the register storage
   10121  1.1  mrg          class, with a function or array type, or with a type that is
   10122  1.1  mrg          not compatible with the type that results after application of
   10123  1.1  mrg          the default argument promotions, the behavior is undefined."
   10124  1.1  mrg       */
   10125  1.1  mrg       else if (DECL_REGISTER (arg))
   10126  1.1  mrg 	{
   10127  1.1  mrg 	  warning_at (current_location,
   10128  1.1  mrg 		      OPT_Wvarargs,
   10129  1.1  mrg 		      "undefined behavior when second parameter of "
   10130  1.1  mrg 		      "%<va_start%> is declared with %<register%> storage");
   10131  1.1  mrg 	}
   10132  1.1  mrg 
   10133  1.1  mrg       /* We want to verify the second parameter just once before the tree
   10134  1.1  mrg 	 optimizers are run and then avoid keeping it in the tree,
   10135  1.1  mrg 	 as otherwise we could warn even for correct code like:
   10136  1.1  mrg 	 void foo (int i, ...)
   10137  1.1  mrg 	 { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
   10138  1.1  mrg       if (va_start_p)
   10139  1.1  mrg 	CALL_EXPR_ARG (exp, 1) = integer_zero_node;
   10140  1.1  mrg       else
   10141  1.1  mrg 	CALL_EXPR_ARG (exp, 0) = integer_zero_node;
   10142  1.1  mrg     }
   10143  1.1  mrg   return false;
   10144  1.1  mrg }
   10145  1.1  mrg 
   10146  1.1  mrg 
   10147  1.1  mrg /* Expand a call EXP to __builtin_object_size.  */
   10148  1.1  mrg 
   10149  1.1  mrg static rtx
   10150  1.1  mrg expand_builtin_object_size (tree exp)
   10151  1.1  mrg {
   10152  1.1  mrg   tree ost;
   10153  1.1  mrg   int object_size_type;
   10154  1.1  mrg   tree fndecl = get_callee_fndecl (exp);
   10155  1.1  mrg 
   10156  1.1  mrg   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   10157  1.1  mrg     {
   10158  1.1  mrg       error ("first argument of %qD must be a pointer, second integer constant",
   10159  1.1  mrg 	     fndecl);
   10160  1.1  mrg       expand_builtin_trap ();
   10161  1.1  mrg       return const0_rtx;
   10162  1.1  mrg     }
   10163  1.1  mrg 
   10164  1.1  mrg   ost = CALL_EXPR_ARG (exp, 1);
   10165  1.1  mrg   STRIP_NOPS (ost);
   10166  1.1  mrg 
   10167  1.1  mrg   if (TREE_CODE (ost) != INTEGER_CST
   10168  1.1  mrg       || tree_int_cst_sgn (ost) < 0
   10169  1.1  mrg       || compare_tree_int (ost, 3) > 0)
   10170  1.1  mrg     {
   10171  1.1  mrg       error ("last argument of %qD is not integer constant between 0 and 3",
   10172  1.1  mrg 	      fndecl);
   10173  1.1  mrg       expand_builtin_trap ();
   10174  1.1  mrg       return const0_rtx;
   10175  1.1  mrg     }
   10176  1.1  mrg 
   10177  1.1  mrg   object_size_type = tree_to_shwi (ost);
   10178  1.1  mrg 
   10179  1.1  mrg   return object_size_type < 2 ? constm1_rtx : const0_rtx;
   10180  1.1  mrg }
   10181  1.1  mrg 
   10182  1.1  mrg /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
   10183  1.1  mrg    FCODE is the BUILT_IN_* to use.
   10184  1.1  mrg    Return NULL_RTX if we failed; the caller should emit a normal call,
   10185  1.1  mrg    otherwise try to get the result in TARGET, if convenient (and in
   10186  1.1  mrg    mode MODE if that's convenient).  */
   10187  1.1  mrg 
   10188  1.1  mrg static rtx
   10189  1.1  mrg expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
   10190  1.1  mrg 			   enum built_in_function fcode)
   10191  1.1  mrg {
   10192  1.1  mrg   if (!validate_arglist (exp,
   10193  1.1  mrg 			 POINTER_TYPE,
   10194  1.1  mrg 			 fcode == BUILT_IN_MEMSET_CHK
   10195  1.1  mrg 			 ? INTEGER_TYPE : POINTER_TYPE,
   10196  1.1  mrg 			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
   10197  1.1  mrg     return NULL_RTX;
   10198  1.1  mrg 
   10199  1.1  mrg   tree dest = CALL_EXPR_ARG (exp, 0);
   10200  1.1  mrg   tree src = CALL_EXPR_ARG (exp, 1);
   10201  1.1  mrg   tree len = CALL_EXPR_ARG (exp, 2);
   10202  1.1  mrg   tree size = CALL_EXPR_ARG (exp, 3);
   10203  1.1  mrg 
   10204  1.1  mrg   /* FIXME: Set access mode to write only for memset et al.  */
   10205  1.1  mrg   bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
   10206  1.1  mrg 				/*srcstr=*/NULL_TREE, size, access_read_write);
   10207  1.1  mrg 
   10208  1.1  mrg   if (!tree_fits_uhwi_p (size))
   10209  1.1  mrg     return NULL_RTX;
   10210  1.1  mrg 
   10211  1.1  mrg   if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
   10212  1.1  mrg     {
   10213  1.1  mrg       /* Avoid transforming the checking call to an ordinary one when
   10214  1.1  mrg 	 an overflow has been detected or when the call couldn't be
   10215  1.1  mrg 	 validated because the size is not constant.  */
   10216  1.1  mrg       if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (size, len))
   10217  1.1  mrg 	return NULL_RTX;
   10218  1.1  mrg 
   10219  1.1  mrg       tree fn = NULL_TREE;
   10220  1.1  mrg       /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
   10221  1.1  mrg 	 mem{cpy,pcpy,move,set} is available.  */
   10222  1.1  mrg       switch (fcode)
   10223  1.1  mrg 	{
   10224  1.1  mrg 	case BUILT_IN_MEMCPY_CHK:
   10225  1.1  mrg 	  fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
   10226  1.1  mrg 	  break;
   10227  1.1  mrg 	case BUILT_IN_MEMPCPY_CHK:
   10228  1.1  mrg 	  fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
   10229  1.1  mrg 	  break;
   10230  1.1  mrg 	case BUILT_IN_MEMMOVE_CHK:
   10231  1.1  mrg 	  fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
   10232  1.1  mrg 	  break;
   10233  1.1  mrg 	case BUILT_IN_MEMSET_CHK:
   10234  1.1  mrg 	  fn = builtin_decl_explicit (BUILT_IN_MEMSET);
   10235  1.1  mrg 	  break;
   10236  1.1  mrg 	default:
   10237  1.1  mrg 	  break;
   10238  1.1  mrg 	}
   10239  1.1  mrg 
   10240  1.1  mrg       if (! fn)
   10241  1.1  mrg 	return NULL_RTX;
   10242  1.1  mrg 
   10243  1.1  mrg       fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
   10244  1.1  mrg       gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   10245  1.1  mrg       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   10246  1.1  mrg       return expand_expr (fn, target, mode, EXPAND_NORMAL);
   10247  1.1  mrg     }
   10248  1.1  mrg   else if (fcode == BUILT_IN_MEMSET_CHK)
   10249  1.1  mrg     return NULL_RTX;
   10250  1.1  mrg   else
   10251  1.1  mrg     {
   10252  1.1  mrg       unsigned int dest_align = get_pointer_alignment (dest);
   10253  1.1  mrg 
   10254  1.1  mrg       /* If DEST is not a pointer type, call the normal function.  */
   10255  1.1  mrg       if (dest_align == 0)
   10256  1.1  mrg 	return NULL_RTX;
   10257  1.1  mrg 
   10258  1.1  mrg       /* If SRC and DEST are the same (and not volatile), do nothing.  */
   10259  1.1  mrg       if (operand_equal_p (src, dest, 0))
   10260  1.1  mrg 	{
   10261  1.1  mrg 	  tree expr;
   10262  1.1  mrg 
   10263  1.1  mrg 	  if (fcode != BUILT_IN_MEMPCPY_CHK)
   10264  1.1  mrg 	    {
   10265  1.1  mrg 	      /* Evaluate and ignore LEN in case it has side-effects.  */
   10266  1.1  mrg 	      expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
   10267  1.1  mrg 	      return expand_expr (dest, target, mode, EXPAND_NORMAL);
   10268  1.1  mrg 	    }
   10269  1.1  mrg 
   10270  1.1  mrg 	  expr = fold_build_pointer_plus (dest, len);
   10271  1.1  mrg 	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
   10272  1.1  mrg 	}
   10273  1.1  mrg 
   10274  1.1  mrg       /* __memmove_chk special case.  */
   10275  1.1  mrg       if (fcode == BUILT_IN_MEMMOVE_CHK)
   10276  1.1  mrg 	{
   10277  1.1  mrg 	  unsigned int src_align = get_pointer_alignment (src);
   10278  1.1  mrg 
   10279  1.1  mrg 	  if (src_align == 0)
   10280  1.1  mrg 	    return NULL_RTX;
   10281  1.1  mrg 
   10282  1.1  mrg 	  /* If src is categorized for a readonly section we can use
   10283  1.1  mrg 	     normal __memcpy_chk.  */
   10284  1.1  mrg 	  if (readonly_data_expr (src))
   10285  1.1  mrg 	    {
   10286  1.1  mrg 	      tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
   10287  1.1  mrg 	      if (!fn)
   10288  1.1  mrg 		return NULL_RTX;
   10289  1.1  mrg 	      fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
   10290  1.1  mrg 					  dest, src, len, size);
   10291  1.1  mrg 	      gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   10292  1.1  mrg 	      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   10293  1.1  mrg 	      return expand_expr (fn, target, mode, EXPAND_NORMAL);
   10294  1.1  mrg 	    }
   10295  1.1  mrg 	}
   10296  1.1  mrg       return NULL_RTX;
   10297  1.1  mrg     }
   10298  1.1  mrg }
   10299  1.1  mrg 
   10300  1.1  mrg /* Emit warning if a buffer overflow is detected at compile time.  */
   10301  1.1  mrg 
   10302  1.1  mrg static void
   10303  1.1  mrg maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
   10304  1.1  mrg {
   10305  1.1  mrg   /* The source string.  */
   10306  1.1  mrg   tree srcstr = NULL_TREE;
   10307  1.1  mrg   /* The size of the destination object returned by __builtin_object_size.  */
   10308  1.1  mrg   tree objsize = NULL_TREE;
   10309  1.1  mrg   /* The string that is being concatenated with (as in __strcat_chk)
   10310  1.1  mrg      or null if it isn't.  */
   10311  1.1  mrg   tree catstr = NULL_TREE;
   10312  1.1  mrg   /* The maximum length of the source sequence in a bounded operation
   10313  1.1  mrg      (such as __strncat_chk) or null if the operation isn't bounded
   10314  1.1  mrg      (such as __strcat_chk).  */
   10315  1.1  mrg   tree maxread = NULL_TREE;
   10316  1.1  mrg   /* The exact size of the access (such as in __strncpy_chk).  */
   10317  1.1  mrg   tree size = NULL_TREE;
   10318  1.1  mrg   /* The access by the function that's checked.  Except for snprintf
   10319  1.1  mrg      both writing and reading is checked.  */
   10320  1.1  mrg   access_mode mode = access_read_write;
   10321  1.1  mrg 
   10322  1.1  mrg   switch (fcode)
   10323  1.1  mrg     {
   10324  1.1  mrg     case BUILT_IN_STRCPY_CHK:
   10325  1.1  mrg     case BUILT_IN_STPCPY_CHK:
   10326  1.1  mrg       srcstr = CALL_EXPR_ARG (exp, 1);
   10327  1.1  mrg       objsize = CALL_EXPR_ARG (exp, 2);
   10328  1.1  mrg       break;
   10329  1.1  mrg 
   10330  1.1  mrg     case BUILT_IN_STRCAT_CHK:
   10331  1.1  mrg       /* For __strcat_chk the warning will be emitted only if overflowing
   10332  1.1  mrg 	 by at least strlen (dest) + 1 bytes.  */
   10333  1.1  mrg       catstr = CALL_EXPR_ARG (exp, 0);
   10334  1.1  mrg       srcstr = CALL_EXPR_ARG (exp, 1);
   10335  1.1  mrg       objsize = CALL_EXPR_ARG (exp, 2);
   10336  1.1  mrg       break;
   10337  1.1  mrg 
   10338  1.1  mrg     case BUILT_IN_STRNCAT_CHK:
   10339  1.1  mrg       catstr = CALL_EXPR_ARG (exp, 0);
   10340  1.1  mrg       srcstr = CALL_EXPR_ARG (exp, 1);
   10341  1.1  mrg       maxread = CALL_EXPR_ARG (exp, 2);
   10342  1.1  mrg       objsize = CALL_EXPR_ARG (exp, 3);
   10343  1.1  mrg       break;
   10344  1.1  mrg 
   10345  1.1  mrg     case BUILT_IN_STRNCPY_CHK:
   10346  1.1  mrg     case BUILT_IN_STPNCPY_CHK:
   10347  1.1  mrg       srcstr = CALL_EXPR_ARG (exp, 1);
   10348  1.1  mrg       size = CALL_EXPR_ARG (exp, 2);
   10349  1.1  mrg       objsize = CALL_EXPR_ARG (exp, 3);
   10350  1.1  mrg       break;
   10351  1.1  mrg 
   10352  1.1  mrg     case BUILT_IN_SNPRINTF_CHK:
   10353  1.1  mrg     case BUILT_IN_VSNPRINTF_CHK:
   10354  1.1  mrg       maxread = CALL_EXPR_ARG (exp, 1);
   10355  1.1  mrg       objsize = CALL_EXPR_ARG (exp, 3);
   10356  1.1  mrg       /* The only checked access the write to the destination.  */
   10357  1.1  mrg       mode = access_write_only;
   10358  1.1  mrg       break;
   10359  1.1  mrg     default:
   10360  1.1  mrg       gcc_unreachable ();
   10361  1.1  mrg     }
   10362  1.1  mrg 
   10363  1.1  mrg   if (catstr && maxread)
   10364  1.1  mrg     {
   10365  1.1  mrg       /* Check __strncat_chk.  There is no way to determine the length
   10366  1.1  mrg 	 of the string to which the source string is being appended so
   10367  1.1  mrg 	 just warn when the length of the source string is not known.  */
   10368  1.1  mrg       check_strncat_sizes (exp, objsize);
   10369  1.1  mrg       return;
   10370  1.1  mrg     }
   10371  1.1  mrg 
   10372  1.1  mrg   check_access (exp, size, maxread, srcstr, objsize, mode);
   10373  1.1  mrg }
   10374  1.1  mrg 
   10375  1.1  mrg /* Emit warning if a buffer overflow is detected at compile time
   10376  1.1  mrg    in __sprintf_chk/__vsprintf_chk calls.  */
   10377  1.1  mrg 
   10378  1.1  mrg static void
   10379  1.1  mrg maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
   10380  1.1  mrg {
   10381  1.1  mrg   tree size, len, fmt;
   10382  1.1  mrg   const char *fmt_str;
   10383  1.1  mrg   int nargs = call_expr_nargs (exp);
   10384  1.1  mrg 
   10385  1.1  mrg   /* Verify the required arguments in the original call.  */
   10386  1.1  mrg 
   10387  1.1  mrg   if (nargs < 4)
   10388  1.1  mrg     return;
   10389  1.1  mrg   size = CALL_EXPR_ARG (exp, 2);
   10390  1.1  mrg   fmt = CALL_EXPR_ARG (exp, 3);
   10391  1.1  mrg 
   10392  1.1  mrg   if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
   10393  1.1  mrg     return;
   10394  1.1  mrg 
   10395  1.1  mrg   /* Check whether the format is a literal string constant.  */
   10396  1.1  mrg   fmt_str = c_getstr (fmt);
   10397  1.1  mrg   if (fmt_str == NULL)
   10398  1.1  mrg     return;
   10399  1.1  mrg 
   10400  1.1  mrg   if (!init_target_chars ())
   10401  1.1  mrg     return;
   10402  1.1  mrg 
   10403  1.1  mrg   /* If the format doesn't contain % args or %%, we know its size.  */
   10404  1.1  mrg   if (strchr (fmt_str, target_percent) == 0)
   10405  1.1  mrg     len = build_int_cstu (size_type_node, strlen (fmt_str));
   10406  1.1  mrg   /* If the format is "%s" and first ... argument is a string literal,
   10407  1.1  mrg      we know it too.  */
   10408  1.1  mrg   else if (fcode == BUILT_IN_SPRINTF_CHK
   10409  1.1  mrg 	   && strcmp (fmt_str, target_percent_s) == 0)
   10410  1.1  mrg     {
   10411  1.1  mrg       tree arg;
   10412  1.1  mrg 
   10413  1.1  mrg       if (nargs < 5)
   10414  1.1  mrg 	return;
   10415  1.1  mrg       arg = CALL_EXPR_ARG (exp, 4);
   10416  1.1  mrg       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
   10417  1.1  mrg 	return;
   10418  1.1  mrg 
   10419  1.1  mrg       len = c_strlen (arg, 1);
   10420  1.1  mrg       if (!len || ! tree_fits_uhwi_p (len))
   10421  1.1  mrg 	return;
   10422  1.1  mrg     }
   10423  1.1  mrg   else
   10424  1.1  mrg     return;
   10425  1.1  mrg 
   10426  1.1  mrg   /* Add one for the terminating nul.  */
   10427  1.1  mrg   len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
   10428  1.1  mrg 
   10429  1.1  mrg   check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
   10430  1.1  mrg 		access_write_only);
   10431  1.1  mrg }
   10432  1.1  mrg 
   10433  1.1  mrg /* Fold a call to __builtin_object_size with arguments PTR and OST,
   10434  1.1  mrg    if possible.  */
   10435  1.1  mrg 
   10436  1.1  mrg static tree
   10437  1.1  mrg fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
   10438  1.1  mrg {
   10439  1.1  mrg   tree bytes;
   10440  1.1  mrg   int object_size_type;
   10441  1.1  mrg 
   10442  1.1  mrg   if (!validate_arg (ptr, POINTER_TYPE)
   10443  1.1  mrg       || !validate_arg (ost, INTEGER_TYPE))
   10444  1.1  mrg     return NULL_TREE;
   10445  1.1  mrg 
   10446  1.1  mrg   STRIP_NOPS (ost);
   10447  1.1  mrg 
   10448  1.1  mrg   if (TREE_CODE (ost) != INTEGER_CST
   10449  1.1  mrg       || tree_int_cst_sgn (ost) < 0
   10450  1.1  mrg       || compare_tree_int (ost, 3) > 0)
   10451  1.1  mrg     return NULL_TREE;
   10452  1.1  mrg 
   10453  1.1  mrg   object_size_type = tree_to_shwi (ost);
   10454  1.1  mrg 
   10455  1.1  mrg   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
   10456  1.1  mrg      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
   10457  1.1  mrg      and (size_t) 0 for types 2 and 3.  */
   10458  1.1  mrg   if (TREE_SIDE_EFFECTS (ptr))
   10459  1.1  mrg     return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
   10460  1.1  mrg 
   10461  1.1  mrg   if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
   10462  1.1  mrg     object_size_type |= OST_DYNAMIC;
   10463  1.1  mrg 
   10464  1.1  mrg   if (TREE_CODE (ptr) == ADDR_EXPR)
   10465  1.1  mrg     {
   10466  1.1  mrg       compute_builtin_object_size (ptr, object_size_type, &bytes);
   10467  1.1  mrg       if ((object_size_type & OST_DYNAMIC)
   10468  1.1  mrg 	  || int_fits_type_p (bytes, size_type_node))
   10469  1.1  mrg 	return fold_convert (size_type_node, bytes);
   10470  1.1  mrg     }
   10471  1.1  mrg   else if (TREE_CODE (ptr) == SSA_NAME)
   10472  1.1  mrg     {
   10473  1.1  mrg       /* If object size is not known yet, delay folding until
   10474  1.1  mrg        later.  Maybe subsequent passes will help determining
   10475  1.1  mrg        it.  */
   10476  1.1  mrg       if (compute_builtin_object_size (ptr, object_size_type, &bytes)
   10477  1.1  mrg 	  && ((object_size_type & OST_DYNAMIC)
   10478  1.1  mrg 	      || int_fits_type_p (bytes, size_type_node)))
   10479  1.1  mrg 	return fold_convert (size_type_node, bytes);
   10480  1.1  mrg     }
   10481  1.1  mrg 
   10482  1.1  mrg   return NULL_TREE;
   10483  1.1  mrg }
   10484  1.1  mrg 
   10485  1.1  mrg /* Builtins with folding operations that operate on "..." arguments
   10486  1.1  mrg    need special handling; we need to store the arguments in a convenient
   10487  1.1  mrg    data structure before attempting any folding.  Fortunately there are
   10488  1.1  mrg    only a few builtins that fall into this category.  FNDECL is the
   10489  1.1  mrg    function, EXP is the CALL_EXPR for the call.  */
   10490  1.1  mrg 
   10491  1.1  mrg static tree
   10492  1.1  mrg fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
   10493  1.1  mrg {
   10494  1.1  mrg   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10495  1.1  mrg   tree ret = NULL_TREE;
   10496  1.1  mrg 
   10497  1.1  mrg   switch (fcode)
   10498  1.1  mrg     {
   10499  1.1  mrg     case BUILT_IN_FPCLASSIFY:
   10500  1.1  mrg       ret = fold_builtin_fpclassify (loc, args, nargs);
   10501  1.1  mrg       break;
   10502  1.1  mrg 
   10503  1.1  mrg     default:
   10504  1.1  mrg       break;
   10505  1.1  mrg     }
   10506  1.1  mrg   if (ret)
   10507  1.1  mrg     {
   10508  1.1  mrg       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   10509  1.1  mrg       SET_EXPR_LOCATION (ret, loc);
   10510  1.1  mrg       suppress_warning (ret);
   10511  1.1  mrg       return ret;
   10512  1.1  mrg     }
   10513  1.1  mrg   return NULL_TREE;
   10514  1.1  mrg }
   10515  1.1  mrg 
   10516  1.1  mrg /* Initialize format string characters in the target charset.  */
   10517  1.1  mrg 
   10518  1.1  mrg bool
   10519  1.1  mrg init_target_chars (void)
   10520  1.1  mrg {
   10521  1.1  mrg   static bool init;
   10522  1.1  mrg   if (!init)
   10523  1.1  mrg     {
   10524  1.1  mrg       target_newline = lang_hooks.to_target_charset ('\n');
   10525  1.1  mrg       target_percent = lang_hooks.to_target_charset ('%');
   10526  1.1  mrg       target_c = lang_hooks.to_target_charset ('c');
   10527  1.1  mrg       target_s = lang_hooks.to_target_charset ('s');
   10528  1.1  mrg       if (target_newline == 0 || target_percent == 0 || target_c == 0
   10529  1.1  mrg 	  || target_s == 0)
   10530  1.1  mrg 	return false;
   10531  1.1  mrg 
   10532  1.1  mrg       target_percent_c[0] = target_percent;
   10533  1.1  mrg       target_percent_c[1] = target_c;
   10534  1.1  mrg       target_percent_c[2] = '\0';
   10535  1.1  mrg 
   10536  1.1  mrg       target_percent_s[0] = target_percent;
   10537  1.1  mrg       target_percent_s[1] = target_s;
   10538  1.1  mrg       target_percent_s[2] = '\0';
   10539  1.1  mrg 
   10540  1.1  mrg       target_percent_s_newline[0] = target_percent;
   10541  1.1  mrg       target_percent_s_newline[1] = target_s;
   10542  1.1  mrg       target_percent_s_newline[2] = target_newline;
   10543  1.1  mrg       target_percent_s_newline[3] = '\0';
   10544  1.1  mrg 
   10545  1.1  mrg       init = true;
   10546  1.1  mrg     }
   10547  1.1  mrg   return true;
   10548  1.1  mrg }
   10549  1.1  mrg 
   10550  1.1  mrg /* Helper function for do_mpfr_arg*().  Ensure M is a normal number
   10551  1.1  mrg    and no overflow/underflow occurred.  INEXACT is true if M was not
   10552  1.1  mrg    exactly calculated.  TYPE is the tree type for the result.  This
   10553  1.1  mrg    function assumes that you cleared the MPFR flags and then
   10554  1.1  mrg    calculated M to see if anything subsequently set a flag prior to
   10555  1.1  mrg    entering this function.  Return NULL_TREE if any checks fail.  */
   10556  1.1  mrg 
   10557  1.1  mrg static tree
   10558  1.1  mrg do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
   10559  1.1  mrg {
   10560  1.1  mrg   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   10561  1.1  mrg      overflow/underflow occurred.  If -frounding-math, proceed iff the
   10562  1.1  mrg      result of calling FUNC was exact.  */
   10563  1.1  mrg   if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
   10564  1.1  mrg       && (!flag_rounding_math || !inexact))
   10565  1.1  mrg     {
   10566  1.1  mrg       REAL_VALUE_TYPE rr;
   10567  1.1  mrg 
   10568  1.1  mrg       real_from_mpfr (&rr, m, type, MPFR_RNDN);
   10569  1.1  mrg       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
   10570  1.1  mrg 	 check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   10571  1.1  mrg 	 but the mpft_t is not, then we underflowed in the
   10572  1.1  mrg 	 conversion.  */
   10573  1.1  mrg       if (real_isfinite (&rr)
   10574  1.1  mrg 	  && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
   10575  1.1  mrg         {
   10576  1.1  mrg 	  REAL_VALUE_TYPE rmode;
   10577  1.1  mrg 
   10578  1.1  mrg 	  real_convert (&rmode, TYPE_MODE (type), &rr);
   10579  1.1  mrg 	  /* Proceed iff the specified mode can hold the value.  */
   10580  1.1  mrg 	  if (real_identical (&rmode, &rr))
   10581  1.1  mrg 	    return build_real (type, rmode);
   10582  1.1  mrg 	}
   10583  1.1  mrg     }
   10584  1.1  mrg   return NULL_TREE;
   10585  1.1  mrg }
   10586  1.1  mrg 
   10587  1.1  mrg /* Helper function for do_mpc_arg*().  Ensure M is a normal complex
   10588  1.1  mrg    number and no overflow/underflow occurred.  INEXACT is true if M
   10589  1.1  mrg    was not exactly calculated.  TYPE is the tree type for the result.
   10590  1.1  mrg    This function assumes that you cleared the MPFR flags and then
   10591  1.1  mrg    calculated M to see if anything subsequently set a flag prior to
   10592  1.1  mrg    entering this function.  Return NULL_TREE if any checks fail, if
   10593  1.1  mrg    FORCE_CONVERT is true, then bypass the checks.  */
   10594  1.1  mrg 
   10595  1.1  mrg static tree
   10596  1.1  mrg do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
   10597  1.1  mrg {
   10598  1.1  mrg   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   10599  1.1  mrg      overflow/underflow occurred.  If -frounding-math, proceed iff the
   10600  1.1  mrg      result of calling FUNC was exact.  */
   10601  1.1  mrg   if (force_convert
   10602  1.1  mrg       || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
   10603  1.1  mrg 	  && !mpfr_overflow_p () && !mpfr_underflow_p ()
   10604  1.1  mrg 	  && (!flag_rounding_math || !inexact)))
   10605  1.1  mrg     {
   10606  1.1  mrg       REAL_VALUE_TYPE re, im;
   10607  1.1  mrg 
   10608  1.1  mrg       real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
   10609  1.1  mrg       real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
   10610  1.1  mrg       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
   10611  1.1  mrg 	 check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   10612  1.1  mrg 	 but the mpft_t is not, then we underflowed in the
   10613  1.1  mrg 	 conversion.  */
   10614  1.1  mrg       if (force_convert
   10615  1.1  mrg 	  || (real_isfinite (&re) && real_isfinite (&im)
   10616  1.1  mrg 	      && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
   10617  1.1  mrg 	      && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
   10618  1.1  mrg         {
   10619  1.1  mrg 	  REAL_VALUE_TYPE re_mode, im_mode;
   10620  1.1  mrg 
   10621  1.1  mrg 	  real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
   10622  1.1  mrg 	  real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
   10623  1.1  mrg 	  /* Proceed iff the specified mode can hold the value.  */
   10624  1.1  mrg 	  if (force_convert
   10625  1.1  mrg 	      || (real_identical (&re_mode, &re)
   10626  1.1  mrg 		  && real_identical (&im_mode, &im)))
   10627  1.1  mrg 	    return build_complex (type, build_real (TREE_TYPE (type), re_mode),
   10628  1.1  mrg 				  build_real (TREE_TYPE (type), im_mode));
   10629  1.1  mrg 	}
   10630  1.1  mrg     }
   10631  1.1  mrg   return NULL_TREE;
   10632  1.1  mrg }
   10633  1.1  mrg 
   10634  1.1  mrg /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
   10635  1.1  mrg    the pointer *(ARG_QUO) and return the result.  The type is taken
   10636  1.1  mrg    from the type of ARG0 and is used for setting the precision of the
   10637  1.1  mrg    calculation and results.  */
   10638  1.1  mrg 
   10639  1.1  mrg static tree
   10640  1.1  mrg do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
   10641  1.1  mrg {
   10642  1.1  mrg   tree const type = TREE_TYPE (arg0);
   10643  1.1  mrg   tree result = NULL_TREE;
   10644  1.1  mrg 
   10645  1.1  mrg   STRIP_NOPS (arg0);
   10646  1.1  mrg   STRIP_NOPS (arg1);
   10647  1.1  mrg 
   10648  1.1  mrg   /* To proceed, MPFR must exactly represent the target floating point
   10649  1.1  mrg      format, which only happens when the target base equals two.  */
   10650  1.1  mrg   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   10651  1.1  mrg       && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
   10652  1.1  mrg       && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
   10653  1.1  mrg     {
   10654  1.1  mrg       const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
   10655  1.1  mrg       const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
   10656  1.1  mrg 
   10657  1.1  mrg       if (real_isfinite (ra0) && real_isfinite (ra1))
   10658  1.1  mrg         {
   10659  1.1  mrg 	  const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   10660  1.1  mrg 	  const int prec = fmt->p;
   10661  1.1  mrg 	  const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   10662  1.1  mrg 	  tree result_rem;
   10663  1.1  mrg 	  long integer_quo;
   10664  1.1  mrg 	  mpfr_t m0, m1;
   10665  1.1  mrg 
   10666  1.1  mrg 	  mpfr_inits2 (prec, m0, m1, NULL);
   10667  1.1  mrg 	  mpfr_from_real (m0, ra0, MPFR_RNDN);
   10668  1.1  mrg 	  mpfr_from_real (m1, ra1, MPFR_RNDN);
   10669  1.1  mrg 	  mpfr_clear_flags ();
   10670  1.1  mrg 	  mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
   10671  1.1  mrg 	  /* Remquo is independent of the rounding mode, so pass
   10672  1.1  mrg 	     inexact=0 to do_mpfr_ckconv().  */
   10673  1.1  mrg 	  result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
   10674  1.1  mrg 	  mpfr_clears (m0, m1, NULL);
   10675  1.1  mrg 	  if (result_rem)
   10676  1.1  mrg 	    {
   10677  1.1  mrg 	      /* MPFR calculates quo in the host's long so it may
   10678  1.1  mrg 		 return more bits in quo than the target int can hold
   10679  1.1  mrg 		 if sizeof(host long) > sizeof(target int).  This can
   10680  1.1  mrg 		 happen even for native compilers in LP64 mode.  In
   10681  1.1  mrg 		 these cases, modulo the quo value with the largest
   10682  1.1  mrg 		 number that the target int can hold while leaving one
   10683  1.1  mrg 		 bit for the sign.  */
   10684  1.1  mrg 	      if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
   10685  1.1  mrg 		integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
   10686  1.1  mrg 
   10687  1.1  mrg 	      /* Dereference the quo pointer argument.  */
   10688  1.1  mrg 	      arg_quo = build_fold_indirect_ref (arg_quo);
   10689  1.1  mrg 	      /* Proceed iff a valid pointer type was passed in.  */
   10690  1.1  mrg 	      if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
   10691  1.1  mrg 	        {
   10692  1.1  mrg 		  /* Set the value. */
   10693  1.1  mrg 		  tree result_quo
   10694  1.1  mrg 		    = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
   10695  1.1  mrg 				   build_int_cst (TREE_TYPE (arg_quo),
   10696  1.1  mrg 						  integer_quo));
   10697  1.1  mrg 		  TREE_SIDE_EFFECTS (result_quo) = 1;
   10698  1.1  mrg 		  /* Combine the quo assignment with the rem.  */
   10699  1.1  mrg 		  result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
   10700  1.1  mrg 						    result_quo, result_rem));
   10701  1.1  mrg 		}
   10702  1.1  mrg 	    }
   10703  1.1  mrg 	}
   10704  1.1  mrg     }
   10705  1.1  mrg   return result;
   10706  1.1  mrg }
   10707  1.1  mrg 
   10708  1.1  mrg /* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
   10709  1.1  mrg    resulting value as a tree with type TYPE.  The mpfr precision is
   10710  1.1  mrg    set to the precision of TYPE.  We assume that this mpfr function
   10711  1.1  mrg    returns zero if the result could be calculated exactly within the
   10712  1.1  mrg    requested precision.  In addition, the integer pointer represented
   10713  1.1  mrg    by ARG_SG will be dereferenced and set to the appropriate signgam
   10714  1.1  mrg    (-1,1) value.  */
   10715  1.1  mrg 
   10716  1.1  mrg static tree
   10717  1.1  mrg do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
   10718  1.1  mrg {
   10719  1.1  mrg   tree result = NULL_TREE;
   10720  1.1  mrg 
   10721  1.1  mrg   STRIP_NOPS (arg);
   10722  1.1  mrg 
   10723  1.1  mrg   /* To proceed, MPFR must exactly represent the target floating point
   10724  1.1  mrg      format, which only happens when the target base equals two.  Also
   10725  1.1  mrg      verify ARG is a constant and that ARG_SG is an int pointer.  */
   10726  1.1  mrg   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   10727  1.1  mrg       && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
   10728  1.1  mrg       && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
   10729  1.1  mrg       && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
   10730  1.1  mrg     {
   10731  1.1  mrg       const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
   10732  1.1  mrg 
   10733  1.1  mrg       /* In addition to NaN and Inf, the argument cannot be zero or a
   10734  1.1  mrg 	 negative integer.  */
   10735  1.1  mrg       if (real_isfinite (ra)
   10736  1.1  mrg 	  && ra->cl != rvc_zero
   10737  1.1  mrg 	  && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
   10738  1.1  mrg         {
   10739  1.1  mrg 	  const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   10740  1.1  mrg 	  const int prec = fmt->p;
   10741  1.1  mrg 	  const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   10742  1.1  mrg 	  int inexact, sg;
   10743  1.1  mrg 	  mpfr_t m;
   10744  1.1  mrg 	  tree result_lg;
   10745  1.1  mrg 
   10746  1.1  mrg 	  mpfr_init2 (m, prec);
   10747  1.1  mrg 	  mpfr_from_real (m, ra, MPFR_RNDN);
   10748  1.1  mrg 	  mpfr_clear_flags ();
   10749  1.1  mrg 	  inexact = mpfr_lgamma (m, &sg, m, rnd);
   10750  1.1  mrg 	  result_lg = do_mpfr_ckconv (m, type, inexact);
   10751  1.1  mrg 	  mpfr_clear (m);
   10752  1.1  mrg 	  if (result_lg)
   10753  1.1  mrg 	    {
   10754  1.1  mrg 	      tree result_sg;
   10755  1.1  mrg 
   10756  1.1  mrg 	      /* Dereference the arg_sg pointer argument.  */
   10757  1.1  mrg 	      arg_sg = build_fold_indirect_ref (arg_sg);
   10758  1.1  mrg 	      /* Assign the signgam value into *arg_sg. */
   10759  1.1  mrg 	      result_sg = fold_build2 (MODIFY_EXPR,
   10760  1.1  mrg 				       TREE_TYPE (arg_sg), arg_sg,
   10761  1.1  mrg 				       build_int_cst (TREE_TYPE (arg_sg), sg));
   10762  1.1  mrg 	      TREE_SIDE_EFFECTS (result_sg) = 1;
   10763  1.1  mrg 	      /* Combine the signgam assignment with the lgamma result.  */
   10764  1.1  mrg 	      result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
   10765  1.1  mrg 						result_sg, result_lg));
   10766  1.1  mrg 	    }
   10767  1.1  mrg 	}
   10768  1.1  mrg     }
   10769  1.1  mrg 
   10770  1.1  mrg   return result;
   10771  1.1  mrg }
   10772  1.1  mrg 
   10773  1.1  mrg /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
   10774  1.1  mrg    mpc function FUNC on it and return the resulting value as a tree
   10775  1.1  mrg    with type TYPE.  The mpfr precision is set to the precision of
   10776  1.1  mrg    TYPE.  We assume that function FUNC returns zero if the result
   10777  1.1  mrg    could be calculated exactly within the requested precision.  If
   10778  1.1  mrg    DO_NONFINITE is true, then fold expressions containing Inf or NaN
   10779  1.1  mrg    in the arguments and/or results.  */
   10780  1.1  mrg 
   10781  1.1  mrg tree
   10782  1.1  mrg do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
   10783  1.1  mrg 	     int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
   10784  1.1  mrg {
   10785  1.1  mrg   tree result = NULL_TREE;
   10786  1.1  mrg 
   10787  1.1  mrg   STRIP_NOPS (arg0);
   10788  1.1  mrg   STRIP_NOPS (arg1);
   10789  1.1  mrg 
   10790  1.1  mrg   /* To proceed, MPFR must exactly represent the target floating point
   10791  1.1  mrg      format, which only happens when the target base equals two.  */
   10792  1.1  mrg   if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
   10793  1.1  mrg       && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
   10794  1.1  mrg       && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
   10795  1.1  mrg       && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
   10796  1.1  mrg       && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
   10797  1.1  mrg     {
   10798  1.1  mrg       const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
   10799  1.1  mrg       const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
   10800  1.1  mrg       const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
   10801  1.1  mrg       const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
   10802  1.1  mrg 
   10803  1.1  mrg       if (do_nonfinite
   10804  1.1  mrg 	  || (real_isfinite (re0) && real_isfinite (im0)
   10805  1.1  mrg 	      && real_isfinite (re1) && real_isfinite (im1)))
   10806  1.1  mrg         {
   10807  1.1  mrg 	  const struct real_format *const fmt =
   10808  1.1  mrg 	    REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
   10809  1.1  mrg 	  const int prec = fmt->p;
   10810  1.1  mrg 	  const mpfr_rnd_t rnd = fmt->round_towards_zero
   10811  1.1  mrg 				 ? MPFR_RNDZ : MPFR_RNDN;
   10812  1.1  mrg 	  const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
   10813  1.1  mrg 	  int inexact;
   10814  1.1  mrg 	  mpc_t m0, m1;
   10815  1.1  mrg 
   10816  1.1  mrg 	  mpc_init2 (m0, prec);
   10817  1.1  mrg 	  mpc_init2 (m1, prec);
   10818  1.1  mrg 	  mpfr_from_real (mpc_realref (m0), re0, rnd);
   10819  1.1  mrg 	  mpfr_from_real (mpc_imagref (m0), im0, rnd);
   10820  1.1  mrg 	  mpfr_from_real (mpc_realref (m1), re1, rnd);
   10821  1.1  mrg 	  mpfr_from_real (mpc_imagref (m1), im1, rnd);
   10822  1.1  mrg 	  mpfr_clear_flags ();
   10823  1.1  mrg 	  inexact = func (m0, m0, m1, crnd);
   10824  1.1  mrg 	  result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
   10825  1.1  mrg 	  mpc_clear (m0);
   10826  1.1  mrg 	  mpc_clear (m1);
   10827  1.1  mrg 	}
   10828  1.1  mrg     }
   10829  1.1  mrg 
   10830  1.1  mrg   return result;
   10831  1.1  mrg }
   10832  1.1  mrg 
   10833  1.1  mrg /* A wrapper function for builtin folding that prevents warnings for
   10834  1.1  mrg    "statement without effect" and the like, caused by removing the
   10835  1.1  mrg    call node earlier than the warning is generated.  */
   10836  1.1  mrg 
   10837  1.1  mrg tree
   10838  1.1  mrg fold_call_stmt (gcall *stmt, bool ignore)
   10839  1.1  mrg {
   10840  1.1  mrg   tree ret = NULL_TREE;
   10841  1.1  mrg   tree fndecl = gimple_call_fndecl (stmt);
   10842  1.1  mrg   location_t loc = gimple_location (stmt);
   10843  1.1  mrg   if (fndecl && fndecl_built_in_p (fndecl)
   10844  1.1  mrg       && !gimple_call_va_arg_pack_p (stmt))
   10845  1.1  mrg     {
   10846  1.1  mrg       int nargs = gimple_call_num_args (stmt);
   10847  1.1  mrg       tree *args = (nargs > 0
   10848  1.1  mrg 		    ? gimple_call_arg_ptr (stmt, 0)
   10849  1.1  mrg 		    : &error_mark_node);
   10850  1.1  mrg 
   10851  1.1  mrg       if (avoid_folding_inline_builtin (fndecl))
   10852  1.1  mrg 	return NULL_TREE;
   10853  1.1  mrg       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   10854  1.1  mrg         {
   10855  1.1  mrg 	  return targetm.fold_builtin (fndecl, nargs, args, ignore);
   10856  1.1  mrg         }
   10857  1.1  mrg       else
   10858  1.1  mrg 	{
   10859  1.1  mrg 	  ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
   10860  1.1  mrg 	  if (ret)
   10861  1.1  mrg 	    {
   10862  1.1  mrg 	      /* Propagate location information from original call to
   10863  1.1  mrg 		 expansion of builtin.  Otherwise things like
   10864  1.1  mrg 		 maybe_emit_chk_warning, that operate on the expansion
   10865  1.1  mrg 		 of a builtin, will use the wrong location information.  */
   10866  1.1  mrg 	      if (gimple_has_location (stmt))
   10867  1.1  mrg                 {
   10868  1.1  mrg 		  tree realret = ret;
   10869  1.1  mrg 		  if (TREE_CODE (ret) == NOP_EXPR)
   10870  1.1  mrg 		    realret = TREE_OPERAND (ret, 0);
   10871  1.1  mrg 		  if (CAN_HAVE_LOCATION_P (realret)
   10872  1.1  mrg 		      && !EXPR_HAS_LOCATION (realret))
   10873  1.1  mrg 		    SET_EXPR_LOCATION (realret, loc);
   10874  1.1  mrg                   return realret;
   10875  1.1  mrg                 }
   10876  1.1  mrg 	      return ret;
   10877  1.1  mrg 	    }
   10878  1.1  mrg 	}
   10879  1.1  mrg     }
   10880  1.1  mrg   return NULL_TREE;
   10881  1.1  mrg }
   10882  1.1  mrg 
   10883  1.1  mrg /* Look up the function in builtin_decl that corresponds to DECL
   10884  1.1  mrg    and set ASMSPEC as its user assembler name.  DECL must be a
   10885  1.1  mrg    function decl that declares a builtin.  */
   10886  1.1  mrg 
   10887  1.1  mrg void
   10888  1.1  mrg set_builtin_user_assembler_name (tree decl, const char *asmspec)
   10889  1.1  mrg {
   10890  1.1  mrg   gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
   10891  1.1  mrg 	      && asmspec != 0);
   10892  1.1  mrg 
   10893  1.1  mrg   tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
   10894  1.1  mrg   set_user_assembler_name (builtin, asmspec);
   10895  1.1  mrg 
   10896  1.1  mrg   if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
   10897  1.1  mrg       && INT_TYPE_SIZE < BITS_PER_WORD)
   10898  1.1  mrg     {
   10899  1.1  mrg       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
   10900  1.1  mrg       set_user_assembler_libfunc ("ffs", asmspec);
   10901  1.1  mrg       set_optab_libfunc (ffs_optab, mode, "ffs");
   10902  1.1  mrg     }
   10903  1.1  mrg }
   10904  1.1  mrg 
   10905  1.1  mrg /* Return true if DECL is a builtin that expands to a constant or similarly
   10906  1.1  mrg    simple code.  */
   10907  1.1  mrg bool
   10908  1.1  mrg is_simple_builtin (tree decl)
   10909  1.1  mrg {
   10910  1.1  mrg   if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
   10911  1.1  mrg     switch (DECL_FUNCTION_CODE (decl))
   10912  1.1  mrg       {
   10913  1.1  mrg 	/* Builtins that expand to constants.  */
   10914  1.1  mrg       case BUILT_IN_CONSTANT_P:
   10915  1.1  mrg       case BUILT_IN_EXPECT:
   10916  1.1  mrg       case BUILT_IN_OBJECT_SIZE:
   10917  1.1  mrg       case BUILT_IN_UNREACHABLE:
   10918  1.1  mrg 	/* Simple register moves or loads from stack.  */
   10919  1.1  mrg       case BUILT_IN_ASSUME_ALIGNED:
   10920  1.1  mrg       case BUILT_IN_RETURN_ADDRESS:
   10921  1.1  mrg       case BUILT_IN_EXTRACT_RETURN_ADDR:
   10922  1.1  mrg       case BUILT_IN_FROB_RETURN_ADDR:
   10923  1.1  mrg       case BUILT_IN_RETURN:
   10924  1.1  mrg       case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
   10925  1.1  mrg       case BUILT_IN_FRAME_ADDRESS:
   10926  1.1  mrg       case BUILT_IN_VA_END:
   10927  1.1  mrg       case BUILT_IN_STACK_SAVE:
   10928  1.1  mrg       case BUILT_IN_STACK_RESTORE:
   10929  1.1  mrg       case BUILT_IN_DWARF_CFA:
   10930  1.1  mrg 	/* Exception state returns or moves registers around.  */
   10931  1.1  mrg       case BUILT_IN_EH_FILTER:
   10932  1.1  mrg       case BUILT_IN_EH_POINTER:
   10933  1.1  mrg       case BUILT_IN_EH_COPY_VALUES:
   10934  1.1  mrg 	return true;
   10935  1.1  mrg 
   10936  1.1  mrg       default:
   10937  1.1  mrg 	return false;
   10938  1.1  mrg       }
   10939  1.1  mrg 
   10940  1.1  mrg   return false;
   10941  1.1  mrg }
   10942  1.1  mrg 
   10943  1.1  mrg /* Return true if DECL is a builtin that is not expensive, i.e., they are
   10944  1.1  mrg    most probably expanded inline into reasonably simple code.  This is a
   10945  1.1  mrg    superset of is_simple_builtin.  */
   10946  1.1  mrg bool
   10947  1.1  mrg is_inexpensive_builtin (tree decl)
   10948  1.1  mrg {
   10949  1.1  mrg   if (!decl)
   10950  1.1  mrg     return false;
   10951  1.1  mrg   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
   10952  1.1  mrg     return true;
   10953  1.1  mrg   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   10954  1.1  mrg     switch (DECL_FUNCTION_CODE (decl))
   10955  1.1  mrg       {
   10956  1.1  mrg       case BUILT_IN_ABS:
   10957  1.1  mrg       CASE_BUILT_IN_ALLOCA:
   10958  1.1  mrg       case BUILT_IN_BSWAP16:
   10959  1.1  mrg       case BUILT_IN_BSWAP32:
   10960  1.1  mrg       case BUILT_IN_BSWAP64:
   10961  1.1  mrg       case BUILT_IN_BSWAP128:
   10962  1.1  mrg       case BUILT_IN_CLZ:
   10963  1.1  mrg       case BUILT_IN_CLZIMAX:
   10964  1.1  mrg       case BUILT_IN_CLZL:
   10965  1.1  mrg       case BUILT_IN_CLZLL:
   10966  1.1  mrg       case BUILT_IN_CTZ:
   10967  1.1  mrg       case BUILT_IN_CTZIMAX:
   10968  1.1  mrg       case BUILT_IN_CTZL:
   10969  1.1  mrg       case BUILT_IN_CTZLL:
   10970  1.1  mrg       case BUILT_IN_FFS:
   10971  1.1  mrg       case BUILT_IN_FFSIMAX:
   10972  1.1  mrg       case BUILT_IN_FFSL:
   10973  1.1  mrg       case BUILT_IN_FFSLL:
   10974  1.1  mrg       case BUILT_IN_IMAXABS:
   10975  1.1  mrg       case BUILT_IN_FINITE:
   10976  1.1  mrg       case BUILT_IN_FINITEF:
   10977  1.1  mrg       case BUILT_IN_FINITEL:
   10978  1.1  mrg       case BUILT_IN_FINITED32:
   10979  1.1  mrg       case BUILT_IN_FINITED64:
   10980  1.1  mrg       case BUILT_IN_FINITED128:
   10981  1.1  mrg       case BUILT_IN_FPCLASSIFY:
   10982  1.1  mrg       case BUILT_IN_ISFINITE:
   10983  1.1  mrg       case BUILT_IN_ISINF_SIGN:
   10984  1.1  mrg       case BUILT_IN_ISINF:
   10985  1.1  mrg       case BUILT_IN_ISINFF:
   10986  1.1  mrg       case BUILT_IN_ISINFL:
   10987  1.1  mrg       case BUILT_IN_ISINFD32:
   10988  1.1  mrg       case BUILT_IN_ISINFD64:
   10989  1.1  mrg       case BUILT_IN_ISINFD128:
   10990  1.1  mrg       case BUILT_IN_ISNAN:
   10991  1.1  mrg       case BUILT_IN_ISNANF:
   10992  1.1  mrg       case BUILT_IN_ISNANL:
   10993  1.1  mrg       case BUILT_IN_ISNAND32:
   10994  1.1  mrg       case BUILT_IN_ISNAND64:
   10995  1.1  mrg       case BUILT_IN_ISNAND128:
   10996  1.1  mrg       case BUILT_IN_ISNORMAL:
   10997  1.1  mrg       case BUILT_IN_ISGREATER:
   10998  1.1  mrg       case BUILT_IN_ISGREATEREQUAL:
   10999  1.1  mrg       case BUILT_IN_ISLESS:
   11000  1.1  mrg       case BUILT_IN_ISLESSEQUAL:
   11001  1.1  mrg       case BUILT_IN_ISLESSGREATER:
   11002  1.1  mrg       case BUILT_IN_ISUNORDERED:
   11003  1.1  mrg       case BUILT_IN_VA_ARG_PACK:
   11004  1.1  mrg       case BUILT_IN_VA_ARG_PACK_LEN:
   11005  1.1  mrg       case BUILT_IN_VA_COPY:
   11006  1.1  mrg       case BUILT_IN_TRAP:
   11007  1.1  mrg       case BUILT_IN_SAVEREGS:
   11008  1.1  mrg       case BUILT_IN_POPCOUNTL:
   11009  1.1  mrg       case BUILT_IN_POPCOUNTLL:
   11010  1.1  mrg       case BUILT_IN_POPCOUNTIMAX:
   11011  1.1  mrg       case BUILT_IN_POPCOUNT:
   11012  1.1  mrg       case BUILT_IN_PARITYL:
   11013  1.1  mrg       case BUILT_IN_PARITYLL:
   11014  1.1  mrg       case BUILT_IN_PARITYIMAX:
   11015  1.1  mrg       case BUILT_IN_PARITY:
   11016  1.1  mrg       case BUILT_IN_LABS:
   11017  1.1  mrg       case BUILT_IN_LLABS:
   11018  1.1  mrg       case BUILT_IN_PREFETCH:
   11019  1.1  mrg       case BUILT_IN_ACC_ON_DEVICE:
   11020  1.1  mrg 	return true;
   11021  1.1  mrg 
   11022  1.1  mrg       default:
   11023  1.1  mrg 	return is_simple_builtin (decl);
   11024  1.1  mrg       }
   11025  1.1  mrg 
   11026  1.1  mrg   return false;
   11027  1.1  mrg }
   11028  1.1  mrg 
   11029  1.1  mrg /* Return true if T is a constant and the value cast to a target char
   11030  1.1  mrg    can be represented by a host char.
   11031  1.1  mrg    Store the casted char constant in *P if so.  */
   11032  1.1  mrg 
   11033  1.1  mrg bool
   11034  1.1  mrg target_char_cst_p (tree t, char *p)
   11035  1.1  mrg {
   11036  1.1  mrg   if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
   11037  1.1  mrg     return false;
   11038  1.1  mrg 
   11039  1.1  mrg   *p = (char)tree_to_uhwi (t);
   11040  1.1  mrg   return true;
   11041  1.1  mrg }
   11042  1.1  mrg 
   11043  1.1  mrg /* Return true if the builtin DECL is implemented in a standard library.
   11044  1.1  mrg    Otherwise return false which doesn't guarantee it is not (thus the list
   11045  1.1  mrg    of handled builtins below may be incomplete).  */
   11046  1.1  mrg 
   11047  1.1  mrg bool
   11048  1.1  mrg builtin_with_linkage_p (tree decl)
   11049  1.1  mrg {
   11050  1.1  mrg   if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   11051  1.1  mrg     switch (DECL_FUNCTION_CODE (decl))
   11052  1.1  mrg     {
   11053  1.1  mrg       CASE_FLT_FN (BUILT_IN_ACOS):
   11054  1.1  mrg       CASE_FLT_FN (BUILT_IN_ACOSH):
   11055  1.1  mrg       CASE_FLT_FN (BUILT_IN_ASIN):
   11056  1.1  mrg       CASE_FLT_FN (BUILT_IN_ASINH):
   11057  1.1  mrg       CASE_FLT_FN (BUILT_IN_ATAN):
   11058  1.1  mrg       CASE_FLT_FN (BUILT_IN_ATANH):
   11059  1.1  mrg       CASE_FLT_FN (BUILT_IN_ATAN2):
   11060  1.1  mrg       CASE_FLT_FN (BUILT_IN_CBRT):
   11061  1.1  mrg       CASE_FLT_FN (BUILT_IN_CEIL):
   11062  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
   11063  1.1  mrg       CASE_FLT_FN (BUILT_IN_COPYSIGN):
   11064  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
   11065  1.1  mrg       CASE_FLT_FN (BUILT_IN_COS):
   11066  1.1  mrg       CASE_FLT_FN (BUILT_IN_COSH):
   11067  1.1  mrg       CASE_FLT_FN (BUILT_IN_ERF):
   11068  1.1  mrg       CASE_FLT_FN (BUILT_IN_ERFC):
   11069  1.1  mrg       CASE_FLT_FN (BUILT_IN_EXP):
   11070  1.1  mrg       CASE_FLT_FN (BUILT_IN_EXP2):
   11071  1.1  mrg       CASE_FLT_FN (BUILT_IN_EXPM1):
   11072  1.1  mrg       CASE_FLT_FN (BUILT_IN_FABS):
   11073  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   11074  1.1  mrg       CASE_FLT_FN (BUILT_IN_FDIM):
   11075  1.1  mrg       CASE_FLT_FN (BUILT_IN_FLOOR):
   11076  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
   11077  1.1  mrg       CASE_FLT_FN (BUILT_IN_FMA):
   11078  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
   11079  1.1  mrg       CASE_FLT_FN (BUILT_IN_FMAX):
   11080  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
   11081  1.1  mrg       CASE_FLT_FN (BUILT_IN_FMIN):
   11082  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
   11083  1.1  mrg       CASE_FLT_FN (BUILT_IN_FMOD):
   11084  1.1  mrg       CASE_FLT_FN (BUILT_IN_FREXP):
   11085  1.1  mrg       CASE_FLT_FN (BUILT_IN_HYPOT):
   11086  1.1  mrg       CASE_FLT_FN (BUILT_IN_ILOGB):
   11087  1.1  mrg       CASE_FLT_FN (BUILT_IN_LDEXP):
   11088  1.1  mrg       CASE_FLT_FN (BUILT_IN_LGAMMA):
   11089  1.1  mrg       CASE_FLT_FN (BUILT_IN_LLRINT):
   11090  1.1  mrg       CASE_FLT_FN (BUILT_IN_LLROUND):
   11091  1.1  mrg       CASE_FLT_FN (BUILT_IN_LOG):
   11092  1.1  mrg       CASE_FLT_FN (BUILT_IN_LOG10):
   11093  1.1  mrg       CASE_FLT_FN (BUILT_IN_LOG1P):
   11094  1.1  mrg       CASE_FLT_FN (BUILT_IN_LOG2):
   11095  1.1  mrg       CASE_FLT_FN (BUILT_IN_LOGB):
   11096  1.1  mrg       CASE_FLT_FN (BUILT_IN_LRINT):
   11097  1.1  mrg       CASE_FLT_FN (BUILT_IN_LROUND):
   11098  1.1  mrg       CASE_FLT_FN (BUILT_IN_MODF):
   11099  1.1  mrg       CASE_FLT_FN (BUILT_IN_NAN):
   11100  1.1  mrg       CASE_FLT_FN (BUILT_IN_NEARBYINT):
   11101  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
   11102  1.1  mrg       CASE_FLT_FN (BUILT_IN_NEXTAFTER):
   11103  1.1  mrg       CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
   11104  1.1  mrg       CASE_FLT_FN (BUILT_IN_POW):
   11105  1.1  mrg       CASE_FLT_FN (BUILT_IN_REMAINDER):
   11106  1.1  mrg       CASE_FLT_FN (BUILT_IN_REMQUO):
   11107  1.1  mrg       CASE_FLT_FN (BUILT_IN_RINT):
   11108  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
   11109  1.1  mrg       CASE_FLT_FN (BUILT_IN_ROUND):
   11110  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
   11111  1.1  mrg       CASE_FLT_FN (BUILT_IN_SCALBLN):
   11112  1.1  mrg       CASE_FLT_FN (BUILT_IN_SCALBN):
   11113  1.1  mrg       CASE_FLT_FN (BUILT_IN_SIN):
   11114  1.1  mrg       CASE_FLT_FN (BUILT_IN_SINH):
   11115  1.1  mrg       CASE_FLT_FN (BUILT_IN_SINCOS):
   11116  1.1  mrg       CASE_FLT_FN (BUILT_IN_SQRT):
   11117  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
   11118  1.1  mrg       CASE_FLT_FN (BUILT_IN_TAN):
   11119  1.1  mrg       CASE_FLT_FN (BUILT_IN_TANH):
   11120  1.1  mrg       CASE_FLT_FN (BUILT_IN_TGAMMA):
   11121  1.1  mrg       CASE_FLT_FN (BUILT_IN_TRUNC):
   11122  1.1  mrg       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
   11123  1.1  mrg 	return true;
   11124  1.1  mrg 
   11125  1.1  mrg       case BUILT_IN_STPCPY:
   11126  1.1  mrg       case BUILT_IN_STPNCPY:
   11127  1.1  mrg 	/* stpcpy is both referenced in libiberty's pex-win32.c and provided
   11128  1.1  mrg 	   by libiberty's stpcpy.c for MinGW targets so we need to return true
   11129  1.1  mrg 	   in order to be able to build libiberty in LTO mode for them.  */
   11130  1.1  mrg 	return true;
   11131  1.1  mrg 
   11132  1.1  mrg       default:
   11133  1.1  mrg 	break;
   11134  1.1  mrg     }
   11135  1.1  mrg   return false;
   11136  1.1  mrg }
   11137  1.1  mrg 
   11138  1.1  mrg /* Return true if OFFRNG is bounded to a subrange of offset values
   11139  1.1  mrg    valid for the largest possible object.  */
   11140  1.1  mrg 
   11141  1.1  mrg bool
   11142  1.1  mrg access_ref::offset_bounded () const
   11143  1.1  mrg {
   11144  1.1  mrg   tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
   11145  1.1  mrg   tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
   11146  1.1  mrg   return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
   11147  1.1  mrg }
   11148  1.1  mrg 
   11149  1.1  mrg /* If CALLEE has known side effects, fill in INFO and return true.
   11150  1.1  mrg    See tree-ssa-structalias.cc:find_func_aliases
   11151  1.1  mrg    for the list of builtins we might need to handle here.  */
   11152  1.1  mrg 
   11153  1.1  mrg attr_fnspec
   11154  1.1  mrg builtin_fnspec (tree callee)
   11155  1.1  mrg {
   11156  1.1  mrg   built_in_function code = DECL_FUNCTION_CODE (callee);
   11157  1.1  mrg 
   11158  1.1  mrg   switch (code)
   11159  1.1  mrg     {
   11160  1.1  mrg       /* All the following functions read memory pointed to by
   11161  1.1  mrg 	 their second argument and write memory pointed to by first
   11162  1.1  mrg 	 argument.
   11163  1.1  mrg 	 strcat/strncat additionally reads memory pointed to by the first
   11164  1.1  mrg 	 argument.  */
   11165  1.1  mrg       case BUILT_IN_STRCAT:
   11166  1.1  mrg       case BUILT_IN_STRCAT_CHK:
   11167  1.1  mrg 	return "1cW 1 ";
   11168  1.1  mrg       case BUILT_IN_STRNCAT:
   11169  1.1  mrg       case BUILT_IN_STRNCAT_CHK:
   11170  1.1  mrg 	return "1cW 13";
   11171  1.1  mrg       case BUILT_IN_STRCPY:
   11172  1.1  mrg       case BUILT_IN_STRCPY_CHK:
   11173  1.1  mrg 	return "1cO 1 ";
   11174  1.1  mrg       case BUILT_IN_STPCPY:
   11175  1.1  mrg       case BUILT_IN_STPCPY_CHK:
   11176  1.1  mrg 	return ".cO 1 ";
   11177  1.1  mrg       case BUILT_IN_STRNCPY:
   11178  1.1  mrg       case BUILT_IN_MEMCPY:
   11179  1.1  mrg       case BUILT_IN_MEMMOVE:
   11180  1.1  mrg       case BUILT_IN_TM_MEMCPY:
   11181  1.1  mrg       case BUILT_IN_TM_MEMMOVE:
   11182  1.1  mrg       case BUILT_IN_STRNCPY_CHK:
   11183  1.1  mrg       case BUILT_IN_MEMCPY_CHK:
   11184  1.1  mrg       case BUILT_IN_MEMMOVE_CHK:
   11185  1.1  mrg 	return "1cO313";
   11186  1.1  mrg       case BUILT_IN_MEMPCPY:
   11187  1.1  mrg       case BUILT_IN_MEMPCPY_CHK:
   11188  1.1  mrg 	return ".cO313";
   11189  1.1  mrg       case BUILT_IN_STPNCPY:
   11190  1.1  mrg       case BUILT_IN_STPNCPY_CHK:
   11191  1.1  mrg 	return ".cO313";
   11192  1.1  mrg       case BUILT_IN_BCOPY:
   11193  1.1  mrg 	return ".c23O3";
   11194  1.1  mrg       case BUILT_IN_BZERO:
   11195  1.1  mrg 	return ".cO2";
   11196  1.1  mrg       case BUILT_IN_MEMCMP:
   11197  1.1  mrg       case BUILT_IN_MEMCMP_EQ:
   11198  1.1  mrg       case BUILT_IN_BCMP:
   11199  1.1  mrg       case BUILT_IN_STRNCMP:
   11200  1.1  mrg       case BUILT_IN_STRNCMP_EQ:
   11201  1.1  mrg       case BUILT_IN_STRNCASECMP:
   11202  1.1  mrg 	return ".cR3R3";
   11203  1.1  mrg 
   11204  1.1  mrg       /* The following functions read memory pointed to by their
   11205  1.1  mrg 	 first argument.  */
   11206  1.1  mrg       CASE_BUILT_IN_TM_LOAD (1):
   11207  1.1  mrg       CASE_BUILT_IN_TM_LOAD (2):
   11208  1.1  mrg       CASE_BUILT_IN_TM_LOAD (4):
   11209  1.1  mrg       CASE_BUILT_IN_TM_LOAD (8):
   11210  1.1  mrg       CASE_BUILT_IN_TM_LOAD (FLOAT):
   11211  1.1  mrg       CASE_BUILT_IN_TM_LOAD (DOUBLE):
   11212  1.1  mrg       CASE_BUILT_IN_TM_LOAD (LDOUBLE):
   11213  1.1  mrg       CASE_BUILT_IN_TM_LOAD (M64):
   11214  1.1  mrg       CASE_BUILT_IN_TM_LOAD (M128):
   11215  1.1  mrg       CASE_BUILT_IN_TM_LOAD (M256):
   11216  1.1  mrg       case BUILT_IN_TM_LOG:
   11217  1.1  mrg       case BUILT_IN_TM_LOG_1:
   11218  1.1  mrg       case BUILT_IN_TM_LOG_2:
   11219  1.1  mrg       case BUILT_IN_TM_LOG_4:
   11220  1.1  mrg       case BUILT_IN_TM_LOG_8:
   11221  1.1  mrg       case BUILT_IN_TM_LOG_FLOAT:
   11222  1.1  mrg       case BUILT_IN_TM_LOG_DOUBLE:
   11223  1.1  mrg       case BUILT_IN_TM_LOG_LDOUBLE:
   11224  1.1  mrg       case BUILT_IN_TM_LOG_M64:
   11225  1.1  mrg       case BUILT_IN_TM_LOG_M128:
   11226  1.1  mrg       case BUILT_IN_TM_LOG_M256:
   11227  1.1  mrg 	return ".cR ";
   11228  1.1  mrg 
   11229  1.1  mrg       case BUILT_IN_INDEX:
   11230  1.1  mrg       case BUILT_IN_RINDEX:
   11231  1.1  mrg       case BUILT_IN_STRCHR:
   11232  1.1  mrg       case BUILT_IN_STRLEN:
   11233  1.1  mrg       case BUILT_IN_STRRCHR:
   11234  1.1  mrg 	return ".cR ";
   11235  1.1  mrg       case BUILT_IN_STRNLEN:
   11236  1.1  mrg 	return ".cR2";
   11237  1.1  mrg 
   11238  1.1  mrg       /* These read memory pointed to by the first argument.
   11239  1.1  mrg 	 Allocating memory does not have any side-effects apart from
   11240  1.1  mrg 	 being the definition point for the pointer.
   11241  1.1  mrg 	 Unix98 specifies that errno is set on allocation failure.  */
   11242  1.1  mrg       case BUILT_IN_STRDUP:
   11243  1.1  mrg 	return "mCR ";
   11244  1.1  mrg       case BUILT_IN_STRNDUP:
   11245  1.1  mrg 	return "mCR2";
   11246  1.1  mrg       /* Allocating memory does not have any side-effects apart from
   11247  1.1  mrg 	 being the definition point for the pointer.  */
   11248  1.1  mrg       case BUILT_IN_MALLOC:
   11249  1.1  mrg       case BUILT_IN_ALIGNED_ALLOC:
   11250  1.1  mrg       case BUILT_IN_CALLOC:
   11251  1.1  mrg       case BUILT_IN_GOMP_ALLOC:
   11252  1.1  mrg 	return "mC";
   11253  1.1  mrg       CASE_BUILT_IN_ALLOCA:
   11254  1.1  mrg 	return "mc";
   11255  1.1  mrg       /* These read memory pointed to by the first argument with size
   11256  1.1  mrg 	 in the third argument.  */
   11257  1.1  mrg       case BUILT_IN_MEMCHR:
   11258  1.1  mrg 	return ".cR3";
   11259  1.1  mrg       /* These read memory pointed to by the first and second arguments.  */
   11260  1.1  mrg       case BUILT_IN_STRSTR:
   11261  1.1  mrg       case BUILT_IN_STRPBRK:
   11262  1.1  mrg       case BUILT_IN_STRCASECMP:
   11263  1.1  mrg       case BUILT_IN_STRCSPN:
   11264  1.1  mrg       case BUILT_IN_STRSPN:
   11265  1.1  mrg       case BUILT_IN_STRCMP:
   11266  1.1  mrg       case BUILT_IN_STRCMP_EQ:
   11267  1.1  mrg 	return ".cR R ";
   11268  1.1  mrg       /* Freeing memory kills the pointed-to memory.  More importantly
   11269  1.1  mrg 	 the call has to serve as a barrier for moving loads and stores
   11270  1.1  mrg 	 across it.  */
   11271  1.1  mrg       case BUILT_IN_STACK_RESTORE:
   11272  1.1  mrg       case BUILT_IN_FREE:
   11273  1.1  mrg       case BUILT_IN_GOMP_FREE:
   11274  1.1  mrg 	return ".co ";
   11275  1.1  mrg       case BUILT_IN_VA_END:
   11276  1.1  mrg 	return ".cO ";
   11277  1.1  mrg       /* Realloc serves both as allocation point and deallocation point.  */
   11278  1.1  mrg       case BUILT_IN_REALLOC:
   11279  1.1  mrg 	return ".Cw ";
   11280  1.1  mrg       case BUILT_IN_GAMMA_R:
   11281  1.1  mrg       case BUILT_IN_GAMMAF_R:
   11282  1.1  mrg       case BUILT_IN_GAMMAL_R:
   11283  1.1  mrg       case BUILT_IN_LGAMMA_R:
   11284  1.1  mrg       case BUILT_IN_LGAMMAF_R:
   11285  1.1  mrg       case BUILT_IN_LGAMMAL_R:
   11286  1.1  mrg 	return ".C. Ot";
   11287  1.1  mrg       case BUILT_IN_FREXP:
   11288  1.1  mrg       case BUILT_IN_FREXPF:
   11289  1.1  mrg       case BUILT_IN_FREXPL:
   11290  1.1  mrg       case BUILT_IN_MODF:
   11291  1.1  mrg       case BUILT_IN_MODFF:
   11292  1.1  mrg       case BUILT_IN_MODFL:
   11293  1.1  mrg 	return ".c. Ot";
   11294  1.1  mrg       case BUILT_IN_REMQUO:
   11295  1.1  mrg       case BUILT_IN_REMQUOF:
   11296  1.1  mrg       case BUILT_IN_REMQUOL:
   11297  1.1  mrg 	return ".c. . Ot";
   11298  1.1  mrg       case BUILT_IN_SINCOS:
   11299  1.1  mrg       case BUILT_IN_SINCOSF:
   11300  1.1  mrg       case BUILT_IN_SINCOSL:
   11301  1.1  mrg 	return ".c. OtOt";
   11302  1.1  mrg       case BUILT_IN_MEMSET:
   11303  1.1  mrg       case BUILT_IN_MEMSET_CHK:
   11304  1.1  mrg       case BUILT_IN_TM_MEMSET:
   11305  1.1  mrg 	return "1cO3";
   11306  1.1  mrg       CASE_BUILT_IN_TM_STORE (1):
   11307  1.1  mrg       CASE_BUILT_IN_TM_STORE (2):
   11308  1.1  mrg       CASE_BUILT_IN_TM_STORE (4):
   11309  1.1  mrg       CASE_BUILT_IN_TM_STORE (8):
   11310  1.1  mrg       CASE_BUILT_IN_TM_STORE (FLOAT):
   11311  1.1  mrg       CASE_BUILT_IN_TM_STORE (DOUBLE):
   11312  1.1  mrg       CASE_BUILT_IN_TM_STORE (LDOUBLE):
   11313  1.1  mrg       CASE_BUILT_IN_TM_STORE (M64):
   11314  1.1  mrg       CASE_BUILT_IN_TM_STORE (M128):
   11315  1.1  mrg       CASE_BUILT_IN_TM_STORE (M256):
   11316  1.1  mrg 	return ".cO ";
   11317  1.1  mrg       case BUILT_IN_STACK_SAVE:
   11318  1.1  mrg       case BUILT_IN_RETURN:
   11319  1.1  mrg       case BUILT_IN_EH_POINTER:
   11320  1.1  mrg       case BUILT_IN_EH_FILTER:
   11321  1.1  mrg       case BUILT_IN_UNWIND_RESUME:
   11322  1.1  mrg       case BUILT_IN_CXA_END_CLEANUP:
   11323  1.1  mrg       case BUILT_IN_EH_COPY_VALUES:
   11324  1.1  mrg       case BUILT_IN_FRAME_ADDRESS:
   11325  1.1  mrg       case BUILT_IN_APPLY_ARGS:
   11326  1.1  mrg       case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
   11327  1.1  mrg       case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
   11328  1.1  mrg       case BUILT_IN_PREFETCH:
   11329  1.1  mrg       case BUILT_IN_DWARF_CFA:
   11330  1.1  mrg       case BUILT_IN_RETURN_ADDRESS:
   11331  1.1  mrg 	return ".c";
   11332  1.1  mrg       case BUILT_IN_ASSUME_ALIGNED:
   11333  1.1  mrg 	return "1cX ";
   11334  1.1  mrg       /* But posix_memalign stores a pointer into the memory pointed to
   11335  1.1  mrg 	 by its first argument.  */
   11336  1.1  mrg       case BUILT_IN_POSIX_MEMALIGN:
   11337  1.1  mrg 	return ".cOt";
   11338  1.1  mrg 
   11339  1.1  mrg       default:
   11340           	return "";
   11341               }
   11342           }
   11343