• Main Page
  • Modules
  • Data Types
  • Files

osprey-gcc/gcc/builtins.c

Go to the documentation of this file.
00001 /* Expand builtin functions.
00002    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
00004 
00005 This file is part of GCC.
00006 
00007 GCC is free software; you can redistribute it and/or modify it under
00008 the terms of the GNU General Public License as published by the Free
00009 Software Foundation; either version 2, or (at your option) any later
00010 version.
00011 
00012 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
00013 WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GCC; see the file COPYING.  If not, write to the Free
00019 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
00020 02111-1307, USA.  */
00021 
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "machmode.h"
00027 #include "real.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "tree-gimple.h"
00031 #include "flags.h"
00032 #include "regs.h"
00033 #include "hard-reg-set.h"
00034 #include "except.h"
00035 #include "function.h"
00036 #include "insn-config.h"
00037 #include "expr.h"
00038 #include "optabs.h"
00039 #include "libfuncs.h"
00040 #include "recog.h"
00041 #include "output.h"
00042 #include "typeclass.h"
00043 #include "toplev.h"
00044 #include "predict.h"
00045 #include "tm_p.h"
00046 #include "target.h"
00047 #include "langhooks.h"
00048 #include "basic-block.h"
00049 #include "tree-mudflap.h"
00050 
00051 #define CALLED_AS_BUILT_IN(NODE) \
00052    (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
00053 
00054 #ifndef PAD_VARARGS_DOWN
00055 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
00056 #endif
00057 
00058 /* Define the names of the builtin function types and codes.  */
00059 const char *const built_in_class_names[4]
00060   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
00061 
00062 #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
00063 const char * built_in_names[(int) END_BUILTINS] =
00064 {
00065 #include "builtins.def"
00066 };
00067 #undef DEF_BUILTIN
00068 
00069 /* Setup an array of _DECL trees, make sure each element is
00070    initialized to NULL_TREE.  */
00071 tree built_in_decls[(int) END_BUILTINS];
00072 /* Declarations used when constructing the builtin implicitly in the compiler.
00073    It may be NULL_TREE when this is invalid (for instance runtime is not
00074    required to implement the function call in all cases).  */
00075 tree implicit_built_in_decls[(int) END_BUILTINS];
00076 
00077 static int get_pointer_alignment (tree, unsigned int);
00078 static const char *c_getstr (tree);
00079 static rtx c_readstr (const char *, enum machine_mode);
00080 static int target_char_cast (tree, char *);
00081 static rtx get_memory_rtx (tree, tree);
00082 static tree build_string_literal (int, const char *);
00083 static int apply_args_size (void);
00084 static int apply_result_size (void);
00085 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
00086 static rtx result_vector (int, rtx);
00087 #endif
00088 static rtx expand_builtin_setjmp (tree, rtx);
00089 static void expand_builtin_update_setjmp_buf (rtx);
00090 static void expand_builtin_prefetch (tree);
00091 static rtx expand_builtin_apply_args (void);
00092 static rtx expand_builtin_apply_args_1 (void);
00093 static rtx expand_builtin_apply (rtx, rtx, rtx);
00094 static void expand_builtin_return (rtx);
00095 static enum type_class type_to_class (tree);
00096 static rtx expand_builtin_classify_type (tree);
00097 static void expand_errno_check (tree, rtx);
00098 static rtx expand_builtin_mathfn (tree, rtx, rtx);
00099 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
00100 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
00101 static rtx expand_builtin_args_info (tree);
00102 static rtx expand_builtin_next_arg (void);
00103 static rtx expand_builtin_va_start (tree);
00104 static rtx expand_builtin_va_end (tree);
00105 static rtx expand_builtin_va_copy (tree);
00106 static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
00107 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
00108 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
00109 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
00110 static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
00111 static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
00112 static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
00113 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
00114 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
00115 static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
00116 static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
00117 static rtx expand_builtin_bcopy (tree);
00118 static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
00119 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
00120 static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
00121 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
00122 static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
00123 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
00124 static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
00125 static rtx expand_builtin_bzero (tree);
00126 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
00127 static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
00128 static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
00129 static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
00130 static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
00131 static rtx expand_builtin_alloca (tree, rtx);
00132 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
00133 static rtx expand_builtin_frame_address (tree, tree);
00134 static rtx expand_builtin_fputs (tree, rtx, bool);
00135 static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
00136 static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
00137 static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
00138 static tree stabilize_va_list (tree, int);
00139 static rtx expand_builtin_expect (tree, rtx);
00140 static tree fold_builtin_constant_p (tree);
00141 static tree fold_builtin_classify_type (tree);
00142 static tree fold_builtin_strlen (tree);
00143 static tree fold_builtin_inf (tree, int);
00144 static tree fold_builtin_nan (tree, tree, int);
00145 static int validate_arglist (tree, ...);
00146 static bool integer_valued_real_p (tree);
00147 static tree fold_trunc_transparent_mathfn (tree);
00148 static bool readonly_data_expr (tree);
00149 static rtx expand_builtin_fabs (tree, rtx, rtx);
00150 static rtx expand_builtin_signbit (tree, rtx);
00151 static tree fold_builtin_cabs (tree, tree);
00152 static tree fold_builtin_sqrt (tree, tree);
00153 static tree fold_builtin_cbrt (tree, tree);
00154 static tree fold_builtin_pow (tree, tree, tree);
00155 static tree fold_builtin_powi (tree, tree, tree);
00156 static tree fold_builtin_sin (tree);
00157 static tree fold_builtin_cos (tree, tree, tree);
00158 static tree fold_builtin_tan (tree);
00159 static tree fold_builtin_atan (tree, tree);
00160 static tree fold_builtin_trunc (tree);
00161 static tree fold_builtin_floor (tree);
00162 static tree fold_builtin_ceil (tree);
00163 static tree fold_builtin_round (tree);
00164 static tree fold_builtin_bitop (tree);
00165 static tree fold_builtin_memcpy (tree);
00166 static tree fold_builtin_mempcpy (tree, tree, int);
00167 static tree fold_builtin_memmove (tree, tree);
00168 static tree fold_builtin_strchr (tree, tree);
00169 static tree fold_builtin_memcmp (tree);
00170 static tree fold_builtin_strcmp (tree);
00171 static tree fold_builtin_strncmp (tree);
00172 static tree fold_builtin_signbit (tree);
00173 static tree fold_builtin_copysign (tree, tree, tree);
00174 static tree fold_builtin_isascii (tree);
00175 static tree fold_builtin_toascii (tree);
00176 static tree fold_builtin_isdigit (tree);
00177 static tree fold_builtin_fabs (tree, tree);
00178 static tree fold_builtin_abs (tree, tree);
00179 static tree fold_builtin_unordered_cmp (tree, enum tree_code, enum tree_code);
00180 static tree fold_builtin_1 (tree, bool);
00181 
00182 static tree fold_builtin_strpbrk (tree, tree);
00183 static tree fold_builtin_strstr (tree, tree);
00184 static tree fold_builtin_strrchr (tree, tree);
00185 static tree fold_builtin_strcat (tree);
00186 static tree fold_builtin_strncat (tree);
00187 static tree fold_builtin_strspn (tree);
00188 static tree fold_builtin_strcspn (tree);
00189 static tree fold_builtin_sprintf (tree, int);
00190 
00191 
00192 /* Return the alignment in bits of EXP, a pointer valued expression.
00193    But don't return more than MAX_ALIGN no matter what.
00194    The alignment returned is, by default, the alignment of the thing that
00195    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
00196 
00197    Otherwise, look at the expression to see if we can do better, i.e., if the
00198    expression is actually pointing at an object whose alignment is tighter.  */
00199 
00200 static int
00201 get_pointer_alignment (tree exp, unsigned int max_align)
00202 {
00203   unsigned int align, inner;
00204 
00205   if (! POINTER_TYPE_P (TREE_TYPE (exp)))
00206     return 0;
00207 
00208   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
00209   align = MIN (align, max_align);
00210 
00211   while (1)
00212     {
00213       switch (TREE_CODE (exp))
00214   {
00215   case NOP_EXPR:
00216   case CONVERT_EXPR:
00217   case NON_LVALUE_EXPR:
00218     exp = TREE_OPERAND (exp, 0);
00219     if (! POINTER_TYPE_P (TREE_TYPE (exp)))
00220       return align;
00221 
00222     inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
00223     align = MIN (inner, max_align);
00224     break;
00225 
00226   case PLUS_EXPR:
00227     /* If sum of pointer + int, restrict our maximum alignment to that
00228        imposed by the integer.  If not, we can't do any better than
00229        ALIGN.  */
00230     if (! host_integerp (TREE_OPERAND (exp, 1), 1))
00231       return align;
00232 
00233     while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
00234       & (max_align / BITS_PER_UNIT - 1))
00235      != 0)
00236       max_align >>= 1;
00237 
00238     exp = TREE_OPERAND (exp, 0);
00239     break;
00240 
00241   case ADDR_EXPR:
00242     /* See what we are pointing at and look at its alignment.  */
00243     exp = TREE_OPERAND (exp, 0);
00244     if (TREE_CODE (exp) == FUNCTION_DECL)
00245       align = FUNCTION_BOUNDARY;
00246     else if (DECL_P (exp))
00247       align = DECL_ALIGN (exp);
00248 #ifdef CONSTANT_ALIGNMENT
00249     else if (CONSTANT_CLASS_P (exp))
00250       align = CONSTANT_ALIGNMENT (exp, align);
00251 #endif
00252     return MIN (align, max_align);
00253 
00254   default:
00255     return align;
00256   }
00257     }
00258 }
00259 
00260 /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
00261    way, because it could contain a zero byte in the middle.
00262    TREE_STRING_LENGTH is the size of the character array, not the string.
00263 
00264    ONLY_VALUE should be nonzero if the result is not going to be emitted
00265    into the instruction stream and zero if it is going to be expanded.
00266    E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
00267    is returned, otherwise NULL, since
00268    len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
00269    evaluate the side-effects.
00270 
00271    The value returned is of type `ssizetype'.
00272 
00273    Unfortunately, string_constant can't access the values of const char
00274    arrays with initializers, so neither can we do so here.  */
00275 
00276 tree
00277 c_strlen (tree src, int only_value)
00278 {
00279   tree offset_node;
00280   HOST_WIDE_INT offset;
00281   int max;
00282   const char *ptr;
00283 
00284   STRIP_NOPS (src);
00285   if (TREE_CODE (src) == COND_EXPR
00286       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
00287     {
00288       tree len1, len2;
00289 
00290       len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
00291       len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
00292       if (tree_int_cst_equal (len1, len2))
00293   return len1;
00294     }
00295 
00296   if (TREE_CODE (src) == COMPOUND_EXPR
00297       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
00298     return c_strlen (TREE_OPERAND (src, 1), only_value);
00299 
00300   src = string_constant (src, &offset_node);
00301   if (src == 0)
00302     return 0;
00303 
00304   max = TREE_STRING_LENGTH (src) - 1;
00305   ptr = TREE_STRING_POINTER (src);
00306 
00307   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
00308     {
00309       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
00310    compute the offset to the following null if we don't know where to
00311    start searching for it.  */
00312       int i;
00313 
00314       for (i = 0; i < max; i++)
00315   if (ptr[i] == 0)
00316     return 0;
00317 
00318       /* We don't know the starting offset, but we do know that the string
00319    has no internal zero bytes.  We can assume that the offset falls
00320    within the bounds of the string; otherwise, the programmer deserves
00321    what he gets.  Subtract the offset from the length of the string,
00322    and return that.  This would perhaps not be valid if we were dealing
00323    with named arrays in addition to literal string constants.  */
00324 
00325       return size_diffop (size_int (max), offset_node);
00326     }
00327 
00328   /* We have a known offset into the string.  Start searching there for
00329      a null character if we can represent it as a single HOST_WIDE_INT.  */
00330   if (offset_node == 0)
00331     offset = 0;
00332   else if (! host_integerp (offset_node, 0))
00333     offset = -1;
00334   else
00335     offset = tree_low_cst (offset_node, 0);
00336 
00337   /* If the offset is known to be out of bounds, warn, and call strlen at
00338      runtime.  */
00339   if (offset < 0 || offset > max)
00340     {
00341       warning ("offset outside bounds of constant string");
00342       return 0;
00343     }
00344 
00345   /* Use strlen to search for the first zero byte.  Since any strings
00346      constructed with build_string will have nulls appended, we win even
00347      if we get handed something like (char[4])"abcd".
00348 
00349      Since OFFSET is our starting index into the string, no further
00350      calculation is needed.  */
00351   return ssize_int (strlen (ptr + offset));
00352 }
00353 
00354 /* Return a char pointer for a C string if it is a string constant
00355    or sum of string constant and integer constant.  */
00356 
00357 static const char *
00358 c_getstr (tree src)
00359 {
00360   tree offset_node;
00361 
00362   src = string_constant (src, &offset_node);
00363   if (src == 0)
00364     return 0;
00365 
00366   if (offset_node == 0)
00367     return TREE_STRING_POINTER (src);
00368   else if (!host_integerp (offset_node, 1)
00369      || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
00370     return 0;
00371 
00372   return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
00373 }
00374 
00375 /* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
00376    GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
00377 
00378 static rtx
00379 c_readstr (const char *str, enum machine_mode mode)
00380 {
00381   HOST_WIDE_INT c[2];
00382   HOST_WIDE_INT ch;
00383   unsigned int i, j;
00384 
00385   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
00386 
00387   c[0] = 0;
00388   c[1] = 0;
00389   ch = 1;
00390   for (i = 0; i < GET_MODE_SIZE (mode); i++)
00391     {
00392       j = i;
00393       if (WORDS_BIG_ENDIAN)
00394   j = GET_MODE_SIZE (mode) - i - 1;
00395       if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
00396     && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
00397   j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
00398       j *= BITS_PER_UNIT;
00399       gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
00400 
00401       if (ch)
00402   ch = (unsigned char) str[i];
00403       c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
00404     }
00405   return immed_double_const (c[0], c[1], mode);
00406 }
00407 
00408 /* Cast a target constant CST to target CHAR and if that value fits into
00409    host char type, return zero and put that value into variable pointed by
00410    P.  */
00411 
00412 static int
00413 target_char_cast (tree cst, char *p)
00414 {
00415   unsigned HOST_WIDE_INT val, hostval;
00416 
00417   if (!host_integerp (cst, 1)
00418       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
00419     return 1;
00420 
00421   val = tree_low_cst (cst, 1);
00422   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
00423     val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
00424 
00425   hostval = val;
00426   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
00427     hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
00428 
00429   if (val != hostval)
00430     return 1;
00431 
00432   *p = hostval;
00433   return 0;
00434 }
00435 
00436 /* Similar to save_expr, but assumes that arbitrary code is not executed
00437    in between the multiple evaluations.  In particular, we assume that a
00438    non-addressable local variable will not be modified.  */
00439 
00440 static tree
00441 builtin_save_expr (tree exp)
00442 {
00443   if (TREE_ADDRESSABLE (exp) == 0
00444       && (TREE_CODE (exp) == PARM_DECL
00445     || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
00446     return exp;
00447 
00448   return save_expr (exp);
00449 }
00450 
00451 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
00452    times to get the address of either a higher stack frame, or a return
00453    address located within it (depending on FNDECL_CODE).  */
00454 
00455 static rtx
00456 expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
00457 {
00458   int i;
00459 
00460 #ifdef INITIAL_FRAME_ADDRESS_RTX
00461   rtx tem = INITIAL_FRAME_ADDRESS_RTX;
00462 #else
00463   rtx tem = hard_frame_pointer_rtx;
00464 #endif
00465 
00466   /* Some machines need special handling before we can access
00467      arbitrary frames.  For example, on the sparc, we must first flush
00468      all register windows to the stack.  */
00469 #ifdef SETUP_FRAME_ADDRESSES
00470   if (count > 0)
00471     SETUP_FRAME_ADDRESSES ();
00472 #endif
00473 
00474   /* On the sparc, the return address is not in the frame, it is in a
00475      register.  There is no way to access it off of the current frame
00476      pointer, but it can be accessed off the previous frame pointer by
00477      reading the value from the register window save area.  */
00478 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
00479   if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
00480     count--;
00481 #endif
00482 
00483   /* Scan back COUNT frames to the specified frame.  */
00484   for (i = 0; i < count; i++)
00485     {
00486       /* Assume the dynamic chain pointer is in the word that the
00487    frame address points to, unless otherwise specified.  */
00488 #ifdef DYNAMIC_CHAIN_ADDRESS
00489       tem = DYNAMIC_CHAIN_ADDRESS (tem);
00490 #endif
00491       tem = memory_address (Pmode, tem);
00492       tem = gen_rtx_MEM (Pmode, tem);
00493       set_mem_alias_set (tem, get_frame_alias_set ());
00494       tem = copy_to_reg (tem);
00495     }
00496 
00497   /* For __builtin_frame_address, return what we've got.  */
00498   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
00499     return tem;
00500 
00501   /* For __builtin_return_address, Get the return address from that
00502      frame.  */
00503 #ifdef RETURN_ADDR_RTX
00504   tem = RETURN_ADDR_RTX (count, tem);
00505 #else
00506   tem = memory_address (Pmode,
00507       plus_constant (tem, GET_MODE_SIZE (Pmode)));
00508   tem = gen_rtx_MEM (Pmode, tem);
00509   set_mem_alias_set (tem, get_frame_alias_set ());
00510 #endif
00511   return tem;
00512 }
00513 
00514 /* Alias set used for setjmp buffer.  */
00515 static HOST_WIDE_INT setjmp_alias_set = -1;
00516 
00517 /* Construct the leading half of a __builtin_setjmp call.  Control will
00518    return to RECEIVER_LABEL.  This is used directly by sjlj exception
00519    handling code.  */
00520 
00521 void
00522 expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
00523 {
00524   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
00525   rtx stack_save;
00526   rtx mem;
00527 
00528   if (setjmp_alias_set == -1)
00529     setjmp_alias_set = new_alias_set ();
00530 
00531   buf_addr = convert_memory_address (Pmode, buf_addr);
00532 
00533   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
00534 
00535   /* We store the frame pointer and the address of receiver_label in
00536      the buffer and use the rest of it for the stack save area, which
00537      is machine-dependent.  */
00538 
00539   mem = gen_rtx_MEM (Pmode, buf_addr);
00540   set_mem_alias_set (mem, setjmp_alias_set);
00541   emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
00542 
00543   mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
00544   set_mem_alias_set (mem, setjmp_alias_set);
00545 
00546   emit_move_insn (validize_mem (mem),
00547       force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
00548 
00549   stack_save = gen_rtx_MEM (sa_mode,
00550           plus_constant (buf_addr,
00551              2 * GET_MODE_SIZE (Pmode)));
00552   set_mem_alias_set (stack_save, setjmp_alias_set);
00553   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
00554 
00555   /* If there is further processing to do, do it.  */
00556 #ifdef HAVE_builtin_setjmp_setup
00557   if (HAVE_builtin_setjmp_setup)
00558     emit_insn (gen_builtin_setjmp_setup (buf_addr));
00559 #endif
00560 
00561   /* Tell optimize_save_area_alloca that extra work is going to
00562      need to go on during alloca.  */
00563   current_function_calls_setjmp = 1;
00564 
00565   /* Set this so all the registers get saved in our frame; we need to be
00566      able to copy the saved values for any registers from frames we unwind.  */
00567   current_function_has_nonlocal_label = 1;
00568 }
00569 
00570 /* Construct the trailing part of a __builtin_setjmp call.
00571    This is used directly by sjlj exception handling code.  */
00572 
00573 void
00574 expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
00575 {
00576   /* Clobber the FP when we get here, so we have to make sure it's
00577      marked as used by this function.  */
00578   emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
00579 
00580   /* Mark the static chain as clobbered here so life information
00581      doesn't get messed up for it.  */
00582   emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
00583 
00584   /* Now put in the code to restore the frame pointer, and argument
00585      pointer, if needed.  */
00586 #ifdef HAVE_nonlocal_goto
00587   if (! HAVE_nonlocal_goto)
00588 #endif
00589     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
00590 
00591 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
00592   if (fixed_regs[ARG_POINTER_REGNUM])
00593     {
00594 #ifdef ELIMINABLE_REGS
00595       size_t i;
00596       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
00597 
00598       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
00599   if (elim_regs[i].from == ARG_POINTER_REGNUM
00600       && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
00601     break;
00602 
00603       if (i == ARRAY_SIZE (elim_regs))
00604 #endif
00605   {
00606     /* Now restore our arg pointer from the address at which it
00607        was saved in our stack frame.  */
00608     emit_move_insn (virtual_incoming_args_rtx,
00609         copy_to_reg (get_arg_pointer_save_area (cfun)));
00610   }
00611     }
00612 #endif
00613 
00614 #ifdef HAVE_builtin_setjmp_receiver
00615   if (HAVE_builtin_setjmp_receiver)
00616     emit_insn (gen_builtin_setjmp_receiver (receiver_label));
00617   else
00618 #endif
00619 #ifdef HAVE_nonlocal_goto_receiver
00620     if (HAVE_nonlocal_goto_receiver)
00621       emit_insn (gen_nonlocal_goto_receiver ());
00622     else
00623 #endif
00624       { /* Nothing */ }
00625 
00626   /* @@@ This is a kludge.  Not all machine descriptions define a blockage
00627      insn, but we must not allow the code we just generated to be reordered
00628      by scheduling.  Specifically, the update of the frame pointer must
00629      happen immediately, not later.  So emit an ASM_INPUT to act as blockage
00630      insn.  */
00631   emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
00632 }
00633 
00634 /* __builtin_setjmp is passed a pointer to an array of five words (not
00635    all will be used on all machines).  It operates similarly to the C
00636    library function of the same name, but is more efficient.  Much of
00637    the code below (and for longjmp) is copied from the handling of
00638    non-local gotos.
00639 
00640    NOTE: This is intended for use by GNAT and the exception handling
00641    scheme in the compiler and will only work in the method used by
00642    them.  */
00643 
00644 static rtx
00645 expand_builtin_setjmp (tree arglist, rtx target)
00646 {
00647   rtx buf_addr, next_lab, cont_lab;
00648 
00649   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
00650     return NULL_RTX;
00651 
00652   if (target == 0 || !REG_P (target)
00653       || REGNO (target) < FIRST_PSEUDO_REGISTER)
00654     target = gen_reg_rtx (TYPE_MODE (integer_type_node));
00655 
00656   buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
00657 
00658   next_lab = gen_label_rtx ();
00659   cont_lab = gen_label_rtx ();
00660 
00661   expand_builtin_setjmp_setup (buf_addr, next_lab);
00662 
00663   /* Set TARGET to zero and branch to the continue label.  Use emit_jump to
00664      ensure that pending stack adjustments are flushed.  */
00665   emit_move_insn (target, const0_rtx);
00666   emit_jump (cont_lab);
00667 
00668   emit_label (next_lab);
00669 
00670   expand_builtin_setjmp_receiver (next_lab);
00671 
00672   /* Set TARGET to one.  */
00673   emit_move_insn (target, const1_rtx);
00674   emit_label (cont_lab);
00675 
00676   /* Tell flow about the strange goings on.  Putting `next_lab' on
00677      `nonlocal_goto_handler_labels' to indicates that function
00678      calls may traverse the arc back to this label.  */
00679 
00680   current_function_has_nonlocal_label = 1;
00681   nonlocal_goto_handler_labels
00682     = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
00683 
00684   return target;
00685 }
00686 
00687 /* __builtin_longjmp is passed a pointer to an array of five words (not
00688    all will be used on all machines).  It operates similarly to the C
00689    library function of the same name, but is more efficient.  Much of
00690    the code below is copied from the handling of non-local gotos.
00691 
00692    NOTE: This is intended for use by GNAT and the exception handling
00693    scheme in the compiler and will only work in the method used by
00694    them.  */
00695 
00696 static void
00697 expand_builtin_longjmp (rtx buf_addr, rtx value)
00698 {
00699   rtx fp, lab, stack, insn, last;
00700   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
00701 
00702   if (setjmp_alias_set == -1)
00703     setjmp_alias_set = new_alias_set ();
00704 
00705   buf_addr = convert_memory_address (Pmode, buf_addr);
00706 
00707   buf_addr = force_reg (Pmode, buf_addr);
00708 
00709   /* We used to store value in static_chain_rtx, but that fails if pointers
00710      are smaller than integers.  We instead require that the user must pass
00711      a second argument of 1, because that is what builtin_setjmp will
00712      return.  This also makes EH slightly more efficient, since we are no
00713      longer copying around a value that we don't care about.  */
00714   gcc_assert (value == const1_rtx);
00715 
00716   last = get_last_insn ();
00717 #ifdef HAVE_builtin_longjmp
00718   if (HAVE_builtin_longjmp)
00719     emit_insn (gen_builtin_longjmp (buf_addr));
00720   else
00721 #endif
00722     {
00723       fp = gen_rtx_MEM (Pmode, buf_addr);
00724       lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
00725                  GET_MODE_SIZE (Pmode)));
00726 
00727       stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
00728                2 * GET_MODE_SIZE (Pmode)));
00729       set_mem_alias_set (fp, setjmp_alias_set);
00730       set_mem_alias_set (lab, setjmp_alias_set);
00731       set_mem_alias_set (stack, setjmp_alias_set);
00732 
00733       /* Pick up FP, label, and SP from the block and jump.  This code is
00734    from expand_goto in stmt.c; see there for detailed comments.  */
00735 #if HAVE_nonlocal_goto
00736       if (HAVE_nonlocal_goto)
00737   /* We have to pass a value to the nonlocal_goto pattern that will
00738      get copied into the static_chain pointer, but it does not matter
00739      what that value is, because builtin_setjmp does not use it.  */
00740   emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
00741       else
00742 #endif
00743   {
00744     lab = copy_to_reg (lab);
00745 
00746     emit_insn (gen_rtx_CLOBBER (VOIDmode,
00747               gen_rtx_MEM (BLKmode,
00748                gen_rtx_SCRATCH (VOIDmode))));
00749     emit_insn (gen_rtx_CLOBBER (VOIDmode,
00750               gen_rtx_MEM (BLKmode,
00751                hard_frame_pointer_rtx)));
00752 
00753     emit_move_insn (hard_frame_pointer_rtx, fp);
00754     emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
00755 
00756     emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
00757     emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
00758     emit_indirect_jump (lab);
00759   }
00760     }
00761 
00762   /* Search backwards and mark the jump insn as a non-local goto.
00763      Note that this precludes the use of __builtin_longjmp to a
00764      __builtin_setjmp target in the same function.  However, we've
00765      already cautioned the user that these functions are for
00766      internal exception handling use only.  */
00767   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
00768     {
00769       gcc_assert (insn != last);
00770 
00771       if (JUMP_P (insn))
00772   {
00773     REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
00774                 REG_NOTES (insn));
00775     break;
00776   }
00777       else if (CALL_P (insn))
00778   break;
00779     }
00780 }
00781 
00782 /* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
00783    and the address of the save area.  */
00784 
00785 static rtx
00786 expand_builtin_nonlocal_goto (tree arglist)
00787 {
00788   tree t_label, t_save_area;
00789   rtx r_label, r_save_area, r_fp, r_sp, insn;
00790 
00791   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
00792     return NULL_RTX;
00793 
00794   t_label = TREE_VALUE (arglist);
00795   arglist = TREE_CHAIN (arglist);
00796   t_save_area = TREE_VALUE (arglist);
00797 
00798   r_label = expand_expr (t_label, NULL_RTX, VOIDmode, 0);
00799   r_label = convert_memory_address (Pmode, r_label);
00800   r_save_area = expand_expr (t_save_area, NULL_RTX, VOIDmode, 0);
00801   r_save_area = convert_memory_address (Pmode, r_save_area);
00802   r_fp = gen_rtx_MEM (Pmode, r_save_area);
00803   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
00804           plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
00805 
00806   current_function_has_nonlocal_goto = 1;
00807 
00808 #if HAVE_nonlocal_goto
00809   /* ??? We no longer need to pass the static chain value, afaik.  */
00810   if (HAVE_nonlocal_goto)
00811     emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
00812   else
00813 #endif
00814     {
00815       r_label = copy_to_reg (r_label);
00816 
00817       emit_insn (gen_rtx_CLOBBER (VOIDmode,
00818           gen_rtx_MEM (BLKmode,
00819                  gen_rtx_SCRATCH (VOIDmode))));
00820 
00821       emit_insn (gen_rtx_CLOBBER (VOIDmode,
00822           gen_rtx_MEM (BLKmode,
00823                  hard_frame_pointer_rtx)));
00824 
00825       /* Restore frame pointer for containing function.
00826    This sets the actual hard register used for the frame pointer
00827    to the location of the function's incoming static chain info.
00828    The non-local goto handler will then adjust it to contain the
00829    proper value and reload the argument pointer, if needed.  */
00830       emit_move_insn (hard_frame_pointer_rtx, r_fp);
00831       emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
00832 
00833       /* USE of hard_frame_pointer_rtx added for consistency;
00834    not clear if really needed.  */
00835       emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
00836       emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
00837       emit_indirect_jump (r_label);
00838     }
00839 
00840   /* Search backwards to the jump insn and mark it as a
00841      non-local goto.  */
00842   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
00843     {
00844       if (JUMP_P (insn))
00845   {
00846     REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
00847                 const0_rtx, REG_NOTES (insn));
00848     break;
00849   }
00850       else if (CALL_P (insn))
00851   break;
00852     }
00853 
00854   return const0_rtx;
00855 }
00856 
00857 /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
00858    (not all will be used on all machines) that was passed to __builtin_setjmp.
00859    It updates the stack pointer in that block to correspond to the current
00860    stack pointer.  */
00861 
00862 static void
00863 expand_builtin_update_setjmp_buf (rtx buf_addr)
00864 {
00865   enum machine_mode sa_mode = Pmode;
00866   rtx stack_save;
00867 
00868 
00869 #ifdef HAVE_save_stack_nonlocal
00870   if (HAVE_save_stack_nonlocal)
00871     sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
00872 #endif
00873 #ifdef STACK_SAVEAREA_MODE
00874   sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
00875 #endif
00876 
00877   stack_save
00878     = gen_rtx_MEM (sa_mode,
00879        memory_address
00880        (sa_mode,
00881         plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
00882 
00883 #ifdef HAVE_setjmp
00884   if (HAVE_setjmp)
00885     emit_insn (gen_setjmp ());
00886 #endif
00887 
00888   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
00889 }
00890 
00891 /* Expand a call to __builtin_prefetch.  For a target that does not support
00892    data prefetch, evaluate the memory address argument in case it has side
00893    effects.  */
00894 
00895 static void
00896 expand_builtin_prefetch (tree arglist)
00897 {
00898   tree arg0, arg1, arg2;
00899   rtx op0, op1, op2;
00900 
00901   if (!validate_arglist (arglist, POINTER_TYPE, 0))
00902     return;
00903 
00904   arg0 = TREE_VALUE (arglist);
00905   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
00906      zero (read) and argument 2 (locality) defaults to 3 (high degree of
00907      locality).  */
00908   if (TREE_CHAIN (arglist))
00909     {
00910       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
00911       if (TREE_CHAIN (TREE_CHAIN (arglist)))
00912   arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
00913       else
00914   arg2 = build_int_cst (NULL_TREE, 3);
00915     }
00916   else
00917     {
00918       arg1 = integer_zero_node;
00919       arg2 = build_int_cst (NULL_TREE, 3);
00920     }
00921 
00922   /* Argument 0 is an address.  */
00923   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
00924 
00925   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
00926   if (TREE_CODE (arg1) != INTEGER_CST)
00927     {
00928       error ("second argument to %<__builtin_prefetch%> must be a constant");
00929       arg1 = integer_zero_node;
00930     }
00931   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
00932   /* Argument 1 must be either zero or one.  */
00933   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
00934     {
00935       warning ("invalid second argument to %<__builtin_prefetch%>;"
00936          " using zero");
00937       op1 = const0_rtx;
00938     }
00939 
00940   /* Argument 2 (locality) must be a compile-time constant int.  */
00941   if (TREE_CODE (arg2) != INTEGER_CST)
00942     {
00943       error ("third argument to %<__builtin_prefetch%> must be a constant");
00944       arg2 = integer_zero_node;
00945     }
00946   op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
00947   /* Argument 2 must be 0, 1, 2, or 3.  */
00948   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
00949     {
00950       warning ("invalid third argument to %<__builtin_prefetch%>; using zero");
00951       op2 = const0_rtx;
00952     }
00953 
00954 #ifdef HAVE_prefetch
00955   if (HAVE_prefetch)
00956     {
00957       if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
00958        (op0,
00959         insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
00960     || (GET_MODE (op0) != Pmode))
00961   {
00962     op0 = convert_memory_address (Pmode, op0);
00963     op0 = force_reg (Pmode, op0);
00964   }
00965       emit_insn (gen_prefetch (op0, op1, op2));
00966     }
00967 #endif
00968 
00969   /* Don't do anything with direct references to volatile memory, but
00970      generate code to handle other side effects.  */
00971   if (!MEM_P (op0) && side_effects_p (op0))
00972     emit_insn (op0);
00973 }
00974 
00975 /* Get a MEM rtx for expression EXP which is the address of an operand
00976    to be used in a string instruction (cmpstrsi, movmemsi, ..).  LEN is
00977    the maximum length of the block of memory that might be accessed or
00978    NULL if unknown.  */
00979 
00980 static rtx
00981 get_memory_rtx (tree exp, tree len)
00982 {
00983   rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
00984   rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
00985 
00986   /* Get an expression we can use to find the attributes to assign to MEM.
00987      If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
00988      we can.  First remove any nops.  */
00989   while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
00990     || TREE_CODE (exp) == NON_LVALUE_EXPR)
00991    && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
00992     exp = TREE_OPERAND (exp, 0);
00993 
00994   if (TREE_CODE (exp) == ADDR_EXPR)
00995     exp = TREE_OPERAND (exp, 0);
00996   else if (POINTER_TYPE_P (TREE_TYPE (exp)))
00997     exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
00998   else
00999     exp = NULL;
01000 
01001   /* Honor attributes derived from exp, except for the alias set
01002      (as builtin stringops may alias with anything) and the size
01003      (as stringops may access multiple array elements).  */
01004   if (exp)
01005     {
01006       set_mem_attributes (mem, exp, 0);
01007 
01008       /* Allow the string and memory builtins to overflow from one
01009    field into another, see http://gcc.gnu.org/PR23561.
01010    Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
01011    memory accessed by the string or memory builtin will fit
01012    within the field.  */
01013       if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
01014   {
01015     tree mem_expr = MEM_EXPR (mem);
01016     HOST_WIDE_INT offset = -1, length = -1;
01017     tree inner = exp;
01018 
01019     while (TREE_CODE (inner) == ARRAY_REF
01020      || TREE_CODE (inner) == NOP_EXPR
01021      || TREE_CODE (inner) == CONVERT_EXPR
01022      || TREE_CODE (inner) == NON_LVALUE_EXPR
01023      || TREE_CODE (inner) == VIEW_CONVERT_EXPR
01024      || TREE_CODE (inner) == SAVE_EXPR)
01025       inner = TREE_OPERAND (inner, 0);
01026 
01027     gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
01028 
01029     if (MEM_OFFSET (mem)
01030         && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
01031       offset = INTVAL (MEM_OFFSET (mem));
01032 
01033     if (offset >= 0 && len && host_integerp (len, 0))
01034       length = tree_low_cst (len, 0);
01035 
01036     while (TREE_CODE (inner) == COMPONENT_REF)
01037       {
01038         tree field = TREE_OPERAND (inner, 1);
01039         gcc_assert (! DECL_BIT_FIELD (field));
01040         gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
01041         gcc_assert (field == TREE_OPERAND (mem_expr, 1));
01042 
01043         if (length >= 0
01044       && TYPE_SIZE_UNIT (TREE_TYPE (inner))
01045       && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
01046     {
01047       HOST_WIDE_INT size
01048         = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
01049       /* If we can prove the memory starting at XEXP (mem, 0)
01050          and ending at XEXP (mem, 0) + LENGTH will fit into
01051          this field, we can keep that COMPONENT_REF in MEM_EXPR.  */
01052       if (offset <= size
01053           && length <= size
01054           && offset + length <= size)
01055         break;
01056     }
01057 
01058         if (offset >= 0
01059       && host_integerp (DECL_FIELD_OFFSET (field), 0))
01060     offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
01061         + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
01062           / BITS_PER_UNIT;
01063         else
01064     {
01065       offset = -1;
01066       length = -1;
01067     }
01068 
01069         mem_expr = TREE_OPERAND (mem_expr, 0);
01070         inner = TREE_OPERAND (inner, 0);
01071       }
01072 
01073     if (mem_expr == NULL)
01074       offset = -1;
01075     if (mem_expr != MEM_EXPR (mem))
01076       {
01077         set_mem_expr (mem, mem_expr);
01078         set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
01079       }
01080   }
01081       set_mem_alias_set (mem, 0);
01082       set_mem_size (mem, NULL_RTX);
01083     }
01084 
01085   return mem;
01086 }
01087 
01088 /* Built-in functions to perform an untyped call and return.  */
01089 
01090 /* For each register that may be used for calling a function, this
01091    gives a mode used to copy the register's value.  VOIDmode indicates
01092    the register is not used for calling a function.  If the machine
01093    has register windows, this gives only the outbound registers.
01094    INCOMING_REGNO gives the corresponding inbound register.  */
01095 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
01096 
01097 /* For each register that may be used for returning values, this gives
01098    a mode used to copy the register's value.  VOIDmode indicates the
01099    register is not used for returning values.  If the machine has
01100    register windows, this gives only the outbound registers.
01101    INCOMING_REGNO gives the corresponding inbound register.  */
01102 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
01103 
01104 /* For each register that may be used for calling a function, this
01105    gives the offset of that register into the block returned by
01106    __builtin_apply_args.  0 indicates that the register is not
01107    used for calling a function.  */
01108 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
01109 
01110 /* Return the size required for the block returned by __builtin_apply_args,
01111    and initialize apply_args_mode.  */
01112 
01113 static int
01114 apply_args_size (void)
01115 {
01116   static int size = -1;
01117   int align;
01118   unsigned int regno;
01119   enum machine_mode mode;
01120 
01121   /* The values computed by this function never change.  */
01122   if (size < 0)
01123     {
01124       /* The first value is the incoming arg-pointer.  */
01125       size = GET_MODE_SIZE (Pmode);
01126 
01127       /* The second value is the structure value address unless this is
01128    passed as an "invisible" first argument.  */
01129       if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
01130   size += GET_MODE_SIZE (Pmode);
01131 
01132       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01133   if (FUNCTION_ARG_REGNO_P (regno))
01134     {
01135       mode = reg_raw_mode[regno];
01136 
01137       gcc_assert (mode != VOIDmode);
01138 
01139       align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
01140       if (size % align != 0)
01141         size = CEIL (size, align) * align;
01142       apply_args_reg_offset[regno] = size;
01143       size += GET_MODE_SIZE (mode);
01144       apply_args_mode[regno] = mode;
01145     }
01146   else
01147     {
01148       apply_args_mode[regno] = VOIDmode;
01149       apply_args_reg_offset[regno] = 0;
01150     }
01151     }
01152   return size;
01153 }
01154 
01155 /* Return the size required for the block returned by __builtin_apply,
01156    and initialize apply_result_mode.  */
01157 
01158 static int
01159 apply_result_size (void)
01160 {
01161   static int size = -1;
01162   int align, regno;
01163   enum machine_mode mode;
01164 
01165   /* The values computed by this function never change.  */
01166   if (size < 0)
01167     {
01168       size = 0;
01169 
01170       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01171   if (FUNCTION_VALUE_REGNO_P (regno))
01172     {
01173       mode = reg_raw_mode[regno];
01174 
01175       gcc_assert (mode != VOIDmode);
01176 
01177       align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
01178       if (size % align != 0)
01179         size = CEIL (size, align) * align;
01180       size += GET_MODE_SIZE (mode);
01181       apply_result_mode[regno] = mode;
01182     }
01183   else
01184     apply_result_mode[regno] = VOIDmode;
01185 
01186       /* Allow targets that use untyped_call and untyped_return to override
01187    the size so that machine-specific information can be stored here.  */
01188 #ifdef APPLY_RESULT_SIZE
01189       size = APPLY_RESULT_SIZE;
01190 #endif
01191     }
01192   return size;
01193 }
01194 
01195 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
01196 /* Create a vector describing the result block RESULT.  If SAVEP is true,
01197    the result block is used to save the values; otherwise it is used to
01198    restore the values.  */
01199 
01200 static rtx
01201 result_vector (int savep, rtx result)
01202 {
01203   int regno, size, align, nelts;
01204   enum machine_mode mode;
01205   rtx reg, mem;
01206   rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
01207 
01208   size = nelts = 0;
01209   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01210     if ((mode = apply_result_mode[regno]) != VOIDmode)
01211       {
01212   align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
01213   if (size % align != 0)
01214     size = CEIL (size, align) * align;
01215   reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
01216   mem = adjust_address (result, mode, size);
01217   savevec[nelts++] = (savep
01218           ? gen_rtx_SET (VOIDmode, mem, reg)
01219           : gen_rtx_SET (VOIDmode, reg, mem));
01220   size += GET_MODE_SIZE (mode);
01221       }
01222   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
01223 }
01224 #endif /* HAVE_untyped_call or HAVE_untyped_return */
01225 
01226 /* Save the state required to perform an untyped call with the same
01227    arguments as were passed to the current function.  */
01228 
01229 static rtx
01230 expand_builtin_apply_args_1 (void)
01231 {
01232   rtx registers, tem;
01233   int size, align, regno;
01234   enum machine_mode mode;
01235   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
01236 
01237   /* Create a block where the arg-pointer, structure value address,
01238      and argument registers can be saved.  */
01239   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
01240 
01241   /* Walk past the arg-pointer and structure value address.  */
01242   size = GET_MODE_SIZE (Pmode);
01243   if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
01244     size += GET_MODE_SIZE (Pmode);
01245 
01246   /* Save each register used in calling a function to the block.  */
01247   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01248     if ((mode = apply_args_mode[regno]) != VOIDmode)
01249       {
01250   align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
01251   if (size % align != 0)
01252     size = CEIL (size, align) * align;
01253 
01254   tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
01255 
01256   emit_move_insn (adjust_address (registers, mode, size), tem);
01257   size += GET_MODE_SIZE (mode);
01258       }
01259 
01260   /* Save the arg pointer to the block.  */
01261   tem = copy_to_reg (virtual_incoming_args_rtx);
01262 #ifdef STACK_GROWS_DOWNWARD
01263   /* We need the pointer as the caller actually passed them to us, not
01264      as we might have pretended they were passed.  Make sure it's a valid
01265      operand, as emit_move_insn isn't expected to handle a PLUS.  */
01266   tem
01267     = force_operand (plus_constant (tem, current_function_pretend_args_size),
01268          NULL_RTX);
01269 #endif
01270   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
01271 
01272   size = GET_MODE_SIZE (Pmode);
01273 
01274   /* Save the structure value address unless this is passed as an
01275      "invisible" first argument.  */
01276   if (struct_incoming_value)
01277     {
01278       emit_move_insn (adjust_address (registers, Pmode, size),
01279           copy_to_reg (struct_incoming_value));
01280       size += GET_MODE_SIZE (Pmode);
01281     }
01282 
01283   /* Return the address of the block.  */
01284   return copy_addr_to_reg (XEXP (registers, 0));
01285 }
01286 
01287 /* __builtin_apply_args returns block of memory allocated on
01288    the stack into which is stored the arg pointer, structure
01289    value address, static chain, and all the registers that might
01290    possibly be used in performing a function call.  The code is
01291    moved to the start of the function so the incoming values are
01292    saved.  */
01293 
01294 static rtx
01295 expand_builtin_apply_args (void)
01296 {
01297   /* Don't do __builtin_apply_args more than once in a function.
01298      Save the result of the first call and reuse it.  */
01299   if (apply_args_value != 0)
01300     return apply_args_value;
01301   {
01302     /* When this function is called, it means that registers must be
01303        saved on entry to this function.  So we migrate the
01304        call to the first insn of this function.  */
01305     rtx temp;
01306     rtx seq;
01307 
01308     start_sequence ();
01309     temp = expand_builtin_apply_args_1 ();
01310     seq = get_insns ();
01311     end_sequence ();
01312 
01313     apply_args_value = temp;
01314 
01315     /* Put the insns after the NOTE that starts the function.
01316        If this is inside a start_sequence, make the outer-level insn
01317        chain current, so the code is placed at the start of the
01318        function.  */
01319     push_topmost_sequence ();
01320     emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
01321     pop_topmost_sequence ();
01322     return temp;
01323   }
01324 }
01325 
01326 /* Perform an untyped call and save the state required to perform an
01327    untyped return of whatever value was returned by the given function.  */
01328 
01329 static rtx
01330 expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
01331 {
01332   int size, align, regno;
01333   enum machine_mode mode;
01334   rtx incoming_args, result, reg, dest, src, call_insn;
01335   rtx old_stack_level = 0;
01336   rtx call_fusage = 0;
01337   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
01338 
01339   arguments = convert_memory_address (Pmode, arguments);
01340 
01341   /* Create a block where the return registers can be saved.  */
01342   result = assign_stack_local (BLKmode, apply_result_size (), -1);
01343 
01344   /* Fetch the arg pointer from the ARGUMENTS block.  */
01345   incoming_args = gen_reg_rtx (Pmode);
01346   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
01347 #ifndef STACK_GROWS_DOWNWARD
01348   incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
01349                incoming_args, 0, OPTAB_LIB_WIDEN);
01350 #endif
01351 
01352   /* Push a new argument block and copy the arguments.  Do not allow
01353      the (potential) memcpy call below to interfere with our stack
01354      manipulations.  */
01355   do_pending_stack_adjust ();
01356   NO_DEFER_POP;
01357 
01358   /* Save the stack with nonlocal if available.  */
01359 #ifdef HAVE_save_stack_nonlocal
01360   if (HAVE_save_stack_nonlocal)
01361     emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
01362   else
01363 #endif
01364     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
01365 
01366   /* Allocate a block of memory onto the stack and copy the memory
01367      arguments to the outgoing arguments address.  */
01368   allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
01369   dest = virtual_outgoing_args_rtx;
01370 #ifndef STACK_GROWS_DOWNWARD
01371   if (GET_CODE (argsize) == CONST_INT)
01372     dest = plus_constant (dest, -INTVAL (argsize));
01373   else
01374     dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
01375 #endif
01376   dest = gen_rtx_MEM (BLKmode, dest);
01377   set_mem_align (dest, PARM_BOUNDARY);
01378   src = gen_rtx_MEM (BLKmode, incoming_args);
01379   set_mem_align (src, PARM_BOUNDARY);
01380   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
01381 
01382   /* Refer to the argument block.  */
01383   apply_args_size ();
01384   arguments = gen_rtx_MEM (BLKmode, arguments);
01385   set_mem_align (arguments, PARM_BOUNDARY);
01386 
01387   /* Walk past the arg-pointer and structure value address.  */
01388   size = GET_MODE_SIZE (Pmode);
01389   if (struct_value)
01390     size += GET_MODE_SIZE (Pmode);
01391 
01392   /* Restore each of the registers previously saved.  Make USE insns
01393      for each of these registers for use in making the call.  */
01394   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01395     if ((mode = apply_args_mode[regno]) != VOIDmode)
01396       {
01397   align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
01398   if (size % align != 0)
01399     size = CEIL (size, align) * align;
01400   reg = gen_rtx_REG (mode, regno);
01401   emit_move_insn (reg, adjust_address (arguments, mode, size));
01402   use_reg (&call_fusage, reg);
01403   size += GET_MODE_SIZE (mode);
01404       }
01405 
01406   /* Restore the structure value address unless this is passed as an
01407      "invisible" first argument.  */
01408   size = GET_MODE_SIZE (Pmode);
01409   if (struct_value)
01410     {
01411       rtx value = gen_reg_rtx (Pmode);
01412       emit_move_insn (value, adjust_address (arguments, Pmode, size));
01413       emit_move_insn (struct_value, value);
01414       if (REG_P (struct_value))
01415   use_reg (&call_fusage, struct_value);
01416       size += GET_MODE_SIZE (Pmode);
01417     }
01418 
01419   /* All arguments and registers used for the call are set up by now!  */
01420   function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
01421 
01422   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
01423      and we don't want to load it into a register as an optimization,
01424      because prepare_call_address already did it if it should be done.  */
01425   if (GET_CODE (function) != SYMBOL_REF)
01426     function = memory_address (FUNCTION_MODE, function);
01427 
01428   /* Generate the actual call instruction and save the return value.  */
01429 #ifdef HAVE_untyped_call
01430   if (HAVE_untyped_call)
01431     emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
01432               result, result_vector (1, result)));
01433   else
01434 #endif
01435 #ifdef HAVE_call_value
01436   if (HAVE_call_value)
01437     {
01438       rtx valreg = 0;
01439 
01440       /* Locate the unique return register.  It is not possible to
01441    express a call that sets more than one return register using
01442    call_value; use untyped_call for that.  In fact, untyped_call
01443    only needs to save the return registers in the given block.  */
01444       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01445   if ((mode = apply_result_mode[regno]) != VOIDmode)
01446     {
01447       gcc_assert (!valreg); /* HAVE_untyped_call required.  */
01448 
01449       valreg = gen_rtx_REG (mode, regno);
01450     }
01451 
01452       emit_call_insn (GEN_CALL_VALUE (valreg,
01453               gen_rtx_MEM (FUNCTION_MODE, function),
01454               const0_rtx, NULL_RTX, const0_rtx));
01455 
01456       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
01457     }
01458   else
01459 #endif
01460     gcc_unreachable ();
01461 
01462   /* Find the CALL insn we just emitted, and attach the register usage
01463      information.  */
01464   call_insn = last_call_insn ();
01465   add_function_usage_to (call_insn, call_fusage);
01466 
01467   /* Restore the stack.  */
01468 #ifdef HAVE_save_stack_nonlocal
01469   if (HAVE_save_stack_nonlocal)
01470     emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
01471   else
01472 #endif
01473     emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
01474 
01475   OK_DEFER_POP;
01476 
01477   /* Return the address of the result block.  */
01478   result = copy_addr_to_reg (XEXP (result, 0));
01479   return convert_memory_address (ptr_mode, result);
01480 }
01481 
01482 /* Perform an untyped return.  */
01483 
01484 static void
01485 expand_builtin_return (rtx result)
01486 {
01487   int size, align, regno;
01488   enum machine_mode mode;
01489   rtx reg;
01490   rtx call_fusage = 0;
01491 
01492   result = convert_memory_address (Pmode, result);
01493 
01494   apply_result_size ();
01495   result = gen_rtx_MEM (BLKmode, result);
01496 
01497 #ifdef HAVE_untyped_return
01498   if (HAVE_untyped_return)
01499     {
01500       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
01501       emit_barrier ();
01502       return;
01503     }
01504 #endif
01505 
01506   /* Restore the return value and note that each value is used.  */
01507   size = 0;
01508   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01509     if ((mode = apply_result_mode[regno]) != VOIDmode)
01510       {
01511   align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
01512   if (size % align != 0)
01513     size = CEIL (size, align) * align;
01514   reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
01515   emit_move_insn (reg, adjust_address (result, mode, size));
01516 
01517   push_to_sequence (call_fusage);
01518   emit_insn (gen_rtx_USE (VOIDmode, reg));
01519   call_fusage = get_insns ();
01520   end_sequence ();
01521   size += GET_MODE_SIZE (mode);
01522       }
01523 
01524   /* Put the USE insns before the return.  */
01525   emit_insn (call_fusage);
01526 
01527   /* Return whatever values was restored by jumping directly to the end
01528      of the function.  */
01529   expand_naked_return ();
01530 }
01531 
01532 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
01533 
01534 static enum type_class
01535 type_to_class (tree type)
01536 {
01537   switch (TREE_CODE (type))
01538     {
01539     case VOID_TYPE:    return void_type_class;
01540     case INTEGER_TYPE:     return integer_type_class;
01541     case CHAR_TYPE:    return char_type_class;
01542     case ENUMERAL_TYPE:    return enumeral_type_class;
01543     case BOOLEAN_TYPE:     return boolean_type_class;
01544     case POINTER_TYPE:     return pointer_type_class;
01545     case REFERENCE_TYPE:   return reference_type_class;
01546     case OFFSET_TYPE:    return offset_type_class;
01547     case REAL_TYPE:    return real_type_class;
01548     case COMPLEX_TYPE:     return complex_type_class;
01549     case FUNCTION_TYPE:    return function_type_class;
01550     case METHOD_TYPE:    return method_type_class;
01551     case RECORD_TYPE:    return record_type_class;
01552     case UNION_TYPE:
01553     case QUAL_UNION_TYPE:  return union_type_class;
01554     case ARRAY_TYPE:     return (TYPE_STRING_FLAG (type)
01555            ? string_type_class : array_type_class);
01556     case FILE_TYPE:    return file_type_class;
01557     case LANG_TYPE:    return lang_type_class;
01558     default:       return no_type_class;
01559     }
01560 }
01561 
01562 /* Expand a call to __builtin_classify_type with arguments found in
01563    ARGLIST.  */
01564 
01565 static rtx
01566 expand_builtin_classify_type (tree arglist)
01567 {
01568   if (arglist != 0)
01569     return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
01570   return GEN_INT (no_type_class);
01571 }
01572 
01573 /* This helper macro, meant to be used in mathfn_built_in below,
01574    determines which among a set of three builtin math functions is
01575    appropriate for a given type mode.  The `F' and `L' cases are
01576    automatically generated from the `double' case.  */
01577 #define CASE_MATHFN(BUILT_IN_MATHFN) \
01578   case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
01579   fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
01580   fcodel = BUILT_IN_MATHFN##L ; break;
01581 
01582 /* Return mathematic function equivalent to FN but operating directly
01583    on TYPE, if available.  If we can't do the conversion, return zero.  */
01584 tree
01585 mathfn_built_in (tree type, enum built_in_function fn)
01586 {
01587   enum built_in_function fcode, fcodef, fcodel;
01588 
01589   switch (fn)
01590     {
01591       CASE_MATHFN (BUILT_IN_ACOS)
01592       CASE_MATHFN (BUILT_IN_ACOSH)
01593       CASE_MATHFN (BUILT_IN_ASIN)
01594       CASE_MATHFN (BUILT_IN_ASINH)
01595       CASE_MATHFN (BUILT_IN_ATAN)
01596       CASE_MATHFN (BUILT_IN_ATAN2)
01597       CASE_MATHFN (BUILT_IN_ATANH)
01598       CASE_MATHFN (BUILT_IN_CBRT)
01599       CASE_MATHFN (BUILT_IN_CEIL)
01600       CASE_MATHFN (BUILT_IN_COPYSIGN)
01601       CASE_MATHFN (BUILT_IN_COS)
01602       CASE_MATHFN (BUILT_IN_COSH)
01603       CASE_MATHFN (BUILT_IN_DREM)
01604       CASE_MATHFN (BUILT_IN_ERF)
01605       CASE_MATHFN (BUILT_IN_ERFC)
01606       CASE_MATHFN (BUILT_IN_EXP)
01607       CASE_MATHFN (BUILT_IN_EXP10)
01608       CASE_MATHFN (BUILT_IN_EXP2)
01609       CASE_MATHFN (BUILT_IN_EXPM1)
01610       CASE_MATHFN (BUILT_IN_FABS)
01611       CASE_MATHFN (BUILT_IN_FDIM)
01612       CASE_MATHFN (BUILT_IN_FLOOR)
01613       CASE_MATHFN (BUILT_IN_FMA)
01614       CASE_MATHFN (BUILT_IN_FMAX)
01615       CASE_MATHFN (BUILT_IN_FMIN)
01616       CASE_MATHFN (BUILT_IN_FMOD)
01617       CASE_MATHFN (BUILT_IN_FREXP)
01618       CASE_MATHFN (BUILT_IN_GAMMA)
01619       CASE_MATHFN (BUILT_IN_HUGE_VAL)
01620       CASE_MATHFN (BUILT_IN_HYPOT)
01621       CASE_MATHFN (BUILT_IN_ILOGB)
01622       CASE_MATHFN (BUILT_IN_INF)
01623       CASE_MATHFN (BUILT_IN_J0)
01624       CASE_MATHFN (BUILT_IN_J1)
01625       CASE_MATHFN (BUILT_IN_JN)
01626       CASE_MATHFN (BUILT_IN_LDEXP)
01627       CASE_MATHFN (BUILT_IN_LGAMMA)
01628       CASE_MATHFN (BUILT_IN_LLRINT)
01629       CASE_MATHFN (BUILT_IN_LLROUND)
01630       CASE_MATHFN (BUILT_IN_LOG)
01631       CASE_MATHFN (BUILT_IN_LOG10)
01632       CASE_MATHFN (BUILT_IN_LOG1P)
01633       CASE_MATHFN (BUILT_IN_LOG2)
01634       CASE_MATHFN (BUILT_IN_LOGB)
01635       CASE_MATHFN (BUILT_IN_LRINT)
01636       CASE_MATHFN (BUILT_IN_LROUND)
01637       CASE_MATHFN (BUILT_IN_MODF)
01638       CASE_MATHFN (BUILT_IN_NAN)
01639       CASE_MATHFN (BUILT_IN_NANS)
01640       CASE_MATHFN (BUILT_IN_NEARBYINT)
01641       CASE_MATHFN (BUILT_IN_NEXTAFTER)
01642       CASE_MATHFN (BUILT_IN_NEXTTOWARD)
01643       CASE_MATHFN (BUILT_IN_POW)
01644       CASE_MATHFN (BUILT_IN_POWI)
01645       CASE_MATHFN (BUILT_IN_POW10)
01646       CASE_MATHFN (BUILT_IN_REMAINDER)
01647       CASE_MATHFN (BUILT_IN_REMQUO)
01648       CASE_MATHFN (BUILT_IN_RINT)
01649       CASE_MATHFN (BUILT_IN_ROUND)
01650       CASE_MATHFN (BUILT_IN_SCALB)
01651       CASE_MATHFN (BUILT_IN_SCALBLN)
01652       CASE_MATHFN (BUILT_IN_SCALBN)
01653       CASE_MATHFN (BUILT_IN_SIGNIFICAND)
01654       CASE_MATHFN (BUILT_IN_SIN)
01655       CASE_MATHFN (BUILT_IN_SINCOS)
01656       CASE_MATHFN (BUILT_IN_SINH)
01657       CASE_MATHFN (BUILT_IN_SQRT)
01658       CASE_MATHFN (BUILT_IN_TAN)
01659       CASE_MATHFN (BUILT_IN_TANH)
01660       CASE_MATHFN (BUILT_IN_TGAMMA)
01661       CASE_MATHFN (BUILT_IN_TRUNC)
01662       CASE_MATHFN (BUILT_IN_Y0)
01663       CASE_MATHFN (BUILT_IN_Y1)
01664       CASE_MATHFN (BUILT_IN_YN)
01665 
01666       default:
01667   return 0;
01668       }
01669 
01670   if (TYPE_MAIN_VARIANT (type) == double_type_node)
01671     return implicit_built_in_decls[fcode];
01672   else if (TYPE_MAIN_VARIANT (type) == float_type_node)
01673     return implicit_built_in_decls[fcodef];
01674   else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
01675     return implicit_built_in_decls[fcodel];
01676   else
01677     return 0;
01678 }
01679 
01680 /* If errno must be maintained, expand the RTL to check if the result,
01681    TARGET, of a built-in function call, EXP, is NaN, and if so set
01682    errno to EDOM.  */
01683 
01684 static void
01685 expand_errno_check (tree exp, rtx target)
01686 {
01687   rtx lab = gen_label_rtx ();
01688 
01689   /* Test the result; if it is NaN, set errno=EDOM because
01690      the argument was not in the domain.  */
01691   emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
01692          0, lab);
01693 
01694 #ifdef TARGET_EDOM
01695   /* If this built-in doesn't throw an exception, set errno directly.  */
01696   if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
01697     {
01698 #ifdef GEN_ERRNO_RTX
01699       rtx errno_rtx = GEN_ERRNO_RTX;
01700 #else
01701       rtx errno_rtx
01702     = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
01703 #endif
01704       emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
01705       emit_label (lab);
01706       return;
01707     }
01708 #endif
01709 
01710   /* We can't set errno=EDOM directly; let the library call do it.
01711      Pop the arguments right away in case the call gets deleted.  */
01712   NO_DEFER_POP;
01713   expand_call (exp, target, 0);
01714   OK_DEFER_POP;
01715   emit_label (lab);
01716 }
01717 
01718 
01719 /* Expand a call to one of the builtin math functions (sqrt, exp, or log).
01720    Return 0 if a normal call should be emitted rather than expanding the
01721    function in-line.  EXP is the expression that is a call to the builtin
01722    function; if convenient, the result should be placed in TARGET.
01723    SUBTARGET may be used as the target for computing one of EXP's operands.  */
01724 
01725 static rtx
01726 expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
01727 {
01728   optab builtin_optab;
01729   rtx op0, insns, before_call;
01730   tree fndecl = get_callee_fndecl (exp);
01731   tree arglist = TREE_OPERAND (exp, 1);
01732   enum machine_mode mode;
01733   bool errno_set = false;
01734   tree arg, narg;
01735 
01736   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
01737     return 0;
01738 
01739   arg = TREE_VALUE (arglist);
01740 
01741   switch (DECL_FUNCTION_CODE (fndecl))
01742     {
01743     case BUILT_IN_SQRT:
01744     case BUILT_IN_SQRTF:
01745     case BUILT_IN_SQRTL:
01746       errno_set = ! tree_expr_nonnegative_p (arg);
01747       builtin_optab = sqrt_optab;
01748       break;
01749     case BUILT_IN_EXP:
01750     case BUILT_IN_EXPF:
01751     case BUILT_IN_EXPL:
01752       errno_set = true; builtin_optab = exp_optab; break;
01753     case BUILT_IN_EXP10:
01754     case BUILT_IN_EXP10F:
01755     case BUILT_IN_EXP10L:
01756     case BUILT_IN_POW10:
01757     case BUILT_IN_POW10F:
01758     case BUILT_IN_POW10L:
01759       errno_set = true; builtin_optab = exp10_optab; break;
01760     case BUILT_IN_EXP2:
01761     case BUILT_IN_EXP2F:
01762     case BUILT_IN_EXP2L:
01763       errno_set = true; builtin_optab = exp2_optab; break;
01764     case BUILT_IN_EXPM1:
01765     case BUILT_IN_EXPM1F:
01766     case BUILT_IN_EXPM1L:
01767       errno_set = true; builtin_optab = expm1_optab; break;
01768     case BUILT_IN_LOGB:
01769     case BUILT_IN_LOGBF:
01770     case BUILT_IN_LOGBL:
01771       errno_set = true; builtin_optab = logb_optab; break;
01772     case BUILT_IN_ILOGB:
01773     case BUILT_IN_ILOGBF:
01774     case BUILT_IN_ILOGBL:
01775       errno_set = true; builtin_optab = ilogb_optab; break;
01776     case BUILT_IN_LOG:
01777     case BUILT_IN_LOGF:
01778     case BUILT_IN_LOGL:
01779       errno_set = true; builtin_optab = log_optab; break;
01780     case BUILT_IN_LOG10:
01781     case BUILT_IN_LOG10F:
01782     case BUILT_IN_LOG10L:
01783       errno_set = true; builtin_optab = log10_optab; break;
01784     case BUILT_IN_LOG2:
01785     case BUILT_IN_LOG2F:
01786     case BUILT_IN_LOG2L:
01787       errno_set = true; builtin_optab = log2_optab; break;
01788     case BUILT_IN_LOG1P:
01789     case BUILT_IN_LOG1PF:
01790     case BUILT_IN_LOG1PL:
01791       errno_set = true; builtin_optab = log1p_optab; break;
01792     case BUILT_IN_ASIN:
01793     case BUILT_IN_ASINF:
01794     case BUILT_IN_ASINL:
01795       builtin_optab = asin_optab; break;
01796     case BUILT_IN_ACOS:
01797     case BUILT_IN_ACOSF:
01798     case BUILT_IN_ACOSL:
01799       builtin_optab = acos_optab; break;
01800     case BUILT_IN_TAN:
01801     case BUILT_IN_TANF:
01802     case BUILT_IN_TANL:
01803       builtin_optab = tan_optab; break;
01804     case BUILT_IN_ATAN:
01805     case BUILT_IN_ATANF:
01806     case BUILT_IN_ATANL:
01807       builtin_optab = atan_optab; break;
01808     case BUILT_IN_FLOOR:
01809     case BUILT_IN_FLOORF:
01810     case BUILT_IN_FLOORL:
01811       builtin_optab = floor_optab; break;
01812     case BUILT_IN_CEIL:
01813     case BUILT_IN_CEILF:
01814     case BUILT_IN_CEILL:
01815       builtin_optab = ceil_optab; break;
01816     case BUILT_IN_TRUNC:
01817     case BUILT_IN_TRUNCF:
01818     case BUILT_IN_TRUNCL:
01819       builtin_optab = btrunc_optab; break;
01820     case BUILT_IN_ROUND:
01821     case BUILT_IN_ROUNDF:
01822     case BUILT_IN_ROUNDL:
01823       builtin_optab = round_optab; break;
01824     case BUILT_IN_NEARBYINT:
01825     case BUILT_IN_NEARBYINTF:
01826     case BUILT_IN_NEARBYINTL:
01827       builtin_optab = nearbyint_optab; break;
01828     case BUILT_IN_RINT:
01829     case BUILT_IN_RINTF:
01830     case BUILT_IN_RINTL:
01831       builtin_optab = rint_optab; break;
01832     default:
01833       gcc_unreachable ();
01834     }
01835 
01836   /* Make a suitable register to place result in.  */
01837   mode = TYPE_MODE (TREE_TYPE (exp));
01838 
01839   if (! flag_errno_math || ! HONOR_NANS (mode))
01840     errno_set = false;
01841 
01842   /* Before working hard, check whether the instruction is available.  */
01843   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
01844     {
01845       target = gen_reg_rtx (mode);
01846 
01847       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
01848    need to expand the argument again.  This way, we will not perform
01849    side-effects more the once.  */
01850       narg = builtin_save_expr (arg);
01851       if (narg != arg)
01852   {
01853     arg = narg;
01854     arglist = build_tree_list (NULL_TREE, arg);
01855     exp = build_function_call_expr (fndecl, arglist);
01856   }
01857 
01858       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
01859 
01860       start_sequence ();
01861 
01862       /* Compute into TARGET.
01863    Set TARGET to wherever the result comes back.  */
01864       target = expand_unop (mode, builtin_optab, op0, target, 0);
01865 
01866       if (target != 0)
01867   {
01868     if (errno_set)
01869       expand_errno_check (exp, target);
01870 
01871     /* Output the entire sequence.  */
01872     insns = get_insns ();
01873     end_sequence ();
01874     emit_insn (insns);
01875     return target;
01876   }
01877 
01878       /* If we were unable to expand via the builtin, stop the sequence
01879    (without outputting the insns) and call to the library function
01880    with the stabilized argument list.  */
01881       end_sequence ();
01882     }
01883 
01884   before_call = get_last_insn ();
01885 
01886   target = expand_call (exp, target, target == const0_rtx);
01887 
01888   /* If this is a sqrt operation and we don't care about errno, try to
01889      attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
01890      This allows the semantics of the libcall to be visible to the RTL
01891      optimizers.  */
01892   if (builtin_optab == sqrt_optab && !errno_set)
01893     {
01894       /* Search backwards through the insns emitted by expand_call looking
01895    for the instruction with the REG_RETVAL note.  */
01896       rtx last = get_last_insn ();
01897       while (last != before_call)
01898   {
01899     if (find_reg_note (last, REG_RETVAL, NULL))
01900       {
01901         rtx note = find_reg_note (last, REG_EQUAL, NULL);
01902         /* Check that the REQ_EQUAL note is an EXPR_LIST with
01903      two elements, i.e. symbol_ref(sqrt) and the operand.  */
01904         if (note
01905       && GET_CODE (note) == EXPR_LIST
01906       && GET_CODE (XEXP (note, 0)) == EXPR_LIST
01907       && XEXP (XEXP (note, 0), 1) != NULL_RTX
01908       && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
01909     {
01910       rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
01911       /* Check operand is a register with expected mode.  */
01912       if (operand
01913           && REG_P (operand)
01914           && GET_MODE (operand) == mode)
01915         {
01916           /* Replace the REG_EQUAL note with a SQRT rtx.  */
01917           rtx equiv = gen_rtx_SQRT (mode, operand);
01918           set_unique_reg_note (last, REG_EQUAL, equiv);
01919         }
01920     }
01921         break;
01922       }
01923     last = PREV_INSN (last);
01924   }
01925     }
01926 
01927   return target;
01928 }
01929 
01930 /* Expand a call to the builtin binary math functions (pow and atan2).
01931    Return 0 if a normal call should be emitted rather than expanding the
01932    function in-line.  EXP is the expression that is a call to the builtin
01933    function; if convenient, the result should be placed in TARGET.
01934    SUBTARGET may be used as the target for computing one of EXP's
01935    operands.  */
01936 
01937 static rtx
01938 expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
01939 {
01940   optab builtin_optab;
01941   rtx op0, op1, insns;
01942   int op1_type = REAL_TYPE;
01943   tree fndecl = get_callee_fndecl (exp);
01944   tree arglist = TREE_OPERAND (exp, 1);
01945   tree arg0, arg1, temp, narg;
01946   enum machine_mode mode;
01947   bool errno_set = true;
01948   bool stable = true;
01949 
01950   if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP)
01951       || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF)
01952       || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
01953     op1_type = INTEGER_TYPE;
01954 
01955   if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
01956     return 0;
01957 
01958   arg0 = TREE_VALUE (arglist);
01959   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
01960 
01961   switch (DECL_FUNCTION_CODE (fndecl))
01962     {
01963     case BUILT_IN_POW:
01964     case BUILT_IN_POWF:
01965     case BUILT_IN_POWL:
01966       builtin_optab = pow_optab; break;
01967     case BUILT_IN_ATAN2:
01968     case BUILT_IN_ATAN2F:
01969     case BUILT_IN_ATAN2L:
01970       builtin_optab = atan2_optab; break;
01971     case BUILT_IN_LDEXP:
01972     case BUILT_IN_LDEXPF:
01973     case BUILT_IN_LDEXPL:
01974       builtin_optab = ldexp_optab; break;
01975     case BUILT_IN_FMOD:
01976     case BUILT_IN_FMODF:
01977     case BUILT_IN_FMODL:
01978       builtin_optab = fmod_optab; break;
01979     case BUILT_IN_DREM:
01980     case BUILT_IN_DREMF:
01981     case BUILT_IN_DREML:
01982       builtin_optab = drem_optab; break;
01983     default:
01984       gcc_unreachable ();
01985     }
01986 
01987   /* Make a suitable register to place result in.  */
01988   mode = TYPE_MODE (TREE_TYPE (exp));
01989 
01990   /* Before working hard, check whether the instruction is available.  */
01991   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
01992     return 0;
01993 
01994   target = gen_reg_rtx (mode);
01995 
01996   if (! flag_errno_math || ! HONOR_NANS (mode))
01997     errno_set = false;
01998 
01999   /* Always stabilize the argument list.  */
02000   narg = builtin_save_expr (arg1);
02001   if (narg != arg1)
02002     {
02003       arg1 = narg;
02004       temp = build_tree_list (NULL_TREE, narg);
02005       stable = false;
02006     }
02007   else
02008     temp = TREE_CHAIN (arglist);
02009 
02010   narg = builtin_save_expr (arg0);
02011   if (narg != arg0)
02012     {
02013       arg0 = narg;
02014       arglist = tree_cons (NULL_TREE, narg, temp);
02015       stable = false;
02016     }
02017   else if (! stable)
02018     arglist = tree_cons (NULL_TREE, arg0, temp);
02019 
02020   if (! stable)
02021     exp = build_function_call_expr (fndecl, arglist);
02022 
02023   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
02024   op1 = expand_expr (arg1, 0, VOIDmode, 0);
02025 
02026   start_sequence ();
02027 
02028   /* Compute into TARGET.
02029      Set TARGET to wherever the result comes back.  */
02030   target = expand_binop (mode, builtin_optab, op0, op1,
02031        target, 0, OPTAB_DIRECT);
02032 
02033   /* If we were unable to expand via the builtin, stop the sequence
02034      (without outputting the insns) and call to the library function
02035      with the stabilized argument list.  */
02036   if (target == 0)
02037     {
02038       end_sequence ();
02039       return expand_call (exp, target, target == const0_rtx);
02040     }
02041 
02042   if (errno_set)
02043     expand_errno_check (exp, target);
02044 
02045   /* Output the entire sequence.  */
02046   insns = get_insns ();
02047   end_sequence ();
02048   emit_insn (insns);
02049 
02050   return target;
02051 }
02052 
02053 /* Expand a call to the builtin sin and cos math functions.
02054    Return 0 if a normal call should be emitted rather than expanding the
02055    function in-line.  EXP is the expression that is a call to the builtin
02056    function; if convenient, the result should be placed in TARGET.
02057    SUBTARGET may be used as the target for computing one of EXP's
02058    operands.  */
02059 
02060 static rtx
02061 expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
02062 {
02063   optab builtin_optab;
02064   rtx op0, insns, before_call;
02065   tree fndecl = get_callee_fndecl (exp);
02066   tree arglist = TREE_OPERAND (exp, 1);
02067   enum machine_mode mode;
02068   bool errno_set = false;
02069   tree arg, narg;
02070 
02071   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
02072     return 0;
02073 
02074   arg = TREE_VALUE (arglist);
02075 
02076   switch (DECL_FUNCTION_CODE (fndecl))
02077     {
02078     case BUILT_IN_SIN:
02079     case BUILT_IN_SINF:
02080     case BUILT_IN_SINL:
02081     case BUILT_IN_COS:
02082     case BUILT_IN_COSF:
02083     case BUILT_IN_COSL:
02084       builtin_optab = sincos_optab; break;
02085     default:
02086       gcc_unreachable ();
02087     }
02088 
02089   /* Make a suitable register to place result in.  */
02090   mode = TYPE_MODE (TREE_TYPE (exp));
02091 
02092   if (! flag_errno_math || ! HONOR_NANS (mode))
02093     errno_set = false;
02094 
02095   /* Check if sincos insn is available, otherwise fallback
02096      to sin or cos insn.  */
02097   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
02098     switch (DECL_FUNCTION_CODE (fndecl))
02099       {
02100       case BUILT_IN_SIN:
02101       case BUILT_IN_SINF:
02102       case BUILT_IN_SINL:
02103   builtin_optab = sin_optab; break;
02104       case BUILT_IN_COS:
02105       case BUILT_IN_COSF:
02106       case BUILT_IN_COSL:
02107   builtin_optab = cos_optab; break;
02108       default:
02109   gcc_unreachable ();
02110       }
02111   }
02112 
02113   /* Before working hard, check whether the instruction is available.  */
02114   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
02115     {
02116       target = gen_reg_rtx (mode);
02117 
02118       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
02119    need to expand the argument again.  This way, we will not perform
02120    side-effects more the once.  */
02121       narg = save_expr (arg);
02122       if (narg != arg)
02123   {
02124     arg = narg;
02125     arglist = build_tree_list (NULL_TREE, arg);
02126     exp = build_function_call_expr (fndecl, arglist);
02127   }
02128 
02129       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
02130 
02131       start_sequence ();
02132 
02133       /* Compute into TARGET.
02134    Set TARGET to wherever the result comes back.  */
02135       if (builtin_optab == sincos_optab)
02136   {
02137     int result;
02138 
02139     switch (DECL_FUNCTION_CODE (fndecl))
02140       {
02141       case BUILT_IN_SIN:
02142       case BUILT_IN_SINF:
02143       case BUILT_IN_SINL:
02144         result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
02145         break;
02146       case BUILT_IN_COS:
02147       case BUILT_IN_COSF:
02148       case BUILT_IN_COSL:
02149         result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
02150         break;
02151       default:
02152         gcc_unreachable ();
02153       }
02154     gcc_assert (result);
02155   }
02156       else
02157   {
02158     target = expand_unop (mode, builtin_optab, op0, target, 0);
02159   }
02160 
02161       if (target != 0)
02162   {
02163     if (errno_set)
02164       expand_errno_check (exp, target);
02165 
02166     /* Output the entire sequence.  */
02167     insns = get_insns ();
02168     end_sequence ();
02169     emit_insn (insns);
02170     return target;
02171   }
02172 
02173       /* If we were unable to expand via the builtin, stop the sequence
02174    (without outputting the insns) and call to the library function
02175    with the stabilized argument list.  */
02176       end_sequence ();
02177     }
02178 
02179   before_call = get_last_insn ();
02180 
02181   target = expand_call (exp, target, target == const0_rtx);
02182 
02183   return target;
02184 }
02185 
02186 /* To evaluate powi(x,n), the floating point value x raised to the
02187    constant integer exponent n, we use a hybrid algorithm that
02188    combines the "window method" with look-up tables.  For an
02189    introduction to exponentiation algorithms and "addition chains",
02190    see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
02191    "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
02192    3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
02193    Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998.  */
02194 
02195 /* Provide a default value for POWI_MAX_MULTS, the maximum number of
02196    multiplications to inline before calling the system library's pow
02197    function.  powi(x,n) requires at worst 2*bits(n)-2 multiplications,
02198    so this default never requires calling pow, powf or powl.  */
02199 
02200 #ifndef POWI_MAX_MULTS
02201 #define POWI_MAX_MULTS  (2*HOST_BITS_PER_WIDE_INT-2)
02202 #endif
02203 
02204 /* The size of the "optimal power tree" lookup table.  All
02205    exponents less than this value are simply looked up in the
02206    powi_table below.  This threshold is also used to size the
02207    cache of pseudo registers that hold intermediate results.  */
02208 #define POWI_TABLE_SIZE 256
02209 
02210 /* The size, in bits of the window, used in the "window method"
02211    exponentiation algorithm.  This is equivalent to a radix of
02212    (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method".  */
02213 #define POWI_WINDOW_SIZE 3
02214 
02215 /* The following table is an efficient representation of an
02216    "optimal power tree".  For each value, i, the corresponding
02217    value, j, in the table states than an optimal evaluation
02218    sequence for calculating pow(x,i) can be found by evaluating
02219    pow(x,j)*pow(x,i-j).  An optimal power tree for the first
02220    100 integers is given in Knuth's "Seminumerical algorithms".  */
02221 
02222 static const unsigned char powi_table[POWI_TABLE_SIZE] =
02223   {
02224       0,   1,   1,   2,   2,   3,   3,   4,  /*   0 -   7 */
02225       4,   6,   5,   6,   6,  10,   7,   9,  /*   8 -  15 */
02226       8,  16,   9,  16,  10,  12,  11,  13,  /*  16 -  23 */
02227      12,  17,  13,  18,  14,  24,  15,  26,  /*  24 -  31 */
02228      16,  17,  17,  19,  18,  33,  19,  26,  /*  32 -  39 */
02229      20,  25,  21,  40,  22,  27,  23,  44,  /*  40 -  47 */
02230      24,  32,  25,  34,  26,  29,  27,  44,  /*  48 -  55 */
02231      28,  31,  29,  34,  30,  60,  31,  36,  /*  56 -  63 */
02232      32,  64,  33,  34,  34,  46,  35,  37,  /*  64 -  71 */
02233      36,  65,  37,  50,  38,  48,  39,  69,  /*  72 -  79 */
02234      40,  49,  41,  43,  42,  51,  43,  58,  /*  80 -  87 */
02235      44,  64,  45,  47,  46,  59,  47,  76,  /*  88 -  95 */
02236      48,  65,  49,  66,  50,  67,  51,  66,  /*  96 - 103 */
02237      52,  70,  53,  74,  54, 104,  55,  74,  /* 104 - 111 */
02238      56,  64,  57,  69,  58,  78,  59,  68,  /* 112 - 119 */
02239      60,  61,  61,  80,  62,  75,  63,  68,  /* 120 - 127 */
02240      64,  65,  65, 128,  66, 129,  67,  90,  /* 128 - 135 */
02241      68,  73,  69, 131,  70,  94,  71,  88,  /* 136 - 143 */
02242      72, 128,  73,  98,  74, 132,  75, 121,  /* 144 - 151 */
02243      76, 102,  77, 124,  78, 132,  79, 106,  /* 152 - 159 */
02244      80,  97,  81, 160,  82,  99,  83, 134,  /* 160 - 167 */
02245      84,  86,  85,  95,  86, 160,  87, 100,  /* 168 - 175 */
02246      88, 113,  89,  98,  90, 107,  91, 122,  /* 176 - 183 */
02247      92, 111,  93, 102,  94, 126,  95, 150,  /* 184 - 191 */
02248      96, 128,  97, 130,  98, 133,  99, 195,  /* 192 - 199 */
02249     100, 128, 101, 123, 102, 164, 103, 138,  /* 200 - 207 */
02250     104, 145, 105, 146, 106, 109, 107, 149,  /* 208 - 215 */
02251     108, 200, 109, 146, 110, 170, 111, 157,  /* 216 - 223 */
02252     112, 128, 113, 130, 114, 182, 115, 132,  /* 224 - 231 */
02253     116, 200, 117, 132, 118, 158, 119, 206,  /* 232 - 239 */
02254     120, 240, 121, 162, 122, 147, 123, 152,  /* 240 - 247 */
02255     124, 166, 125, 214, 126, 138, 127, 153,  /* 248 - 255 */
02256   };
02257 
02258 
02259 /* Return the number of multiplications required to calculate
02260    powi(x,n) where n is less than POWI_TABLE_SIZE.  This is a
02261    subroutine of powi_cost.  CACHE is an array indicating
02262    which exponents have already been calculated.  */
02263 
02264 static int
02265 powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
02266 {
02267   /* If we've already calculated this exponent, then this evaluation
02268      doesn't require any additional multiplications.  */
02269   if (cache[n])
02270     return 0;
02271 
02272   cache[n] = true;
02273   return powi_lookup_cost (n - powi_table[n], cache)
02274    + powi_lookup_cost (powi_table[n], cache) + 1;
02275 }
02276 
02277 /* Return the number of multiplications required to calculate
02278    powi(x,n) for an arbitrary x, given the exponent N.  This
02279    function needs to be kept in sync with expand_powi below.  */
02280 
02281 static int
02282 powi_cost (HOST_WIDE_INT n)
02283 {
02284   bool cache[POWI_TABLE_SIZE];
02285   unsigned HOST_WIDE_INT digit;
02286   unsigned HOST_WIDE_INT val;
02287   int result;
02288 
02289   if (n == 0)
02290     return 0;
02291 
02292   /* Ignore the reciprocal when calculating the cost.  */
02293   val = (n < 0) ? -n : n;
02294 
02295   /* Initialize the exponent cache.  */
02296   memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
02297   cache[1] = true;
02298 
02299   result = 0;
02300 
02301   while (val >= POWI_TABLE_SIZE)
02302     {
02303       if (val & 1)
02304   {
02305     digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
02306     result += powi_lookup_cost (digit, cache)
02307         + POWI_WINDOW_SIZE + 1;
02308     val >>= POWI_WINDOW_SIZE;
02309   }
02310       else
02311   {
02312     val >>= 1;
02313     result++;
02314   }
02315     }
02316 
02317   return result + powi_lookup_cost (val, cache);
02318 }
02319 
02320 /* Recursive subroutine of expand_powi.  This function takes the array,
02321    CACHE, of already calculated exponents and an exponent N and returns
02322    an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE.  */
02323 
02324 static rtx
02325 expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
02326 {
02327   unsigned HOST_WIDE_INT digit;
02328   rtx target, result;
02329   rtx op0, op1;
02330 
02331   if (n < POWI_TABLE_SIZE)
02332     {
02333       if (cache[n])
02334         return cache[n];
02335 
02336       target = gen_reg_rtx (mode);
02337       cache[n] = target;
02338 
02339       op0 = expand_powi_1 (mode, n - powi_table[n], cache);
02340       op1 = expand_powi_1 (mode, powi_table[n], cache);
02341     }
02342   else if (n & 1)
02343     {
02344       target = gen_reg_rtx (mode);
02345       digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
02346       op0 = expand_powi_1 (mode, n - digit, cache);
02347       op1 = expand_powi_1 (mode, digit, cache);
02348     }
02349   else
02350     {
02351       target = gen_reg_rtx (mode);
02352       op0 = expand_powi_1 (mode, n >> 1, cache);
02353       op1 = op0;
02354     }
02355 
02356   result = expand_mult (mode, op0, op1, target, 0);
02357   if (result != target)
02358     emit_move_insn (target, result);
02359   return target;
02360 }
02361 
02362 /* Expand the RTL to evaluate powi(x,n) in mode MODE.  X is the
02363    floating point operand in mode MODE, and N is the exponent.  This
02364    function needs to be kept in sync with powi_cost above.  */
02365 
02366 static rtx
02367 expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
02368 {
02369   unsigned HOST_WIDE_INT val;
02370   rtx cache[POWI_TABLE_SIZE];
02371   rtx result;
02372 
02373   if (n == 0)
02374     return CONST1_RTX (mode);
02375 
02376   val = (n < 0) ? -n : n;
02377 
02378   memset (cache, 0, sizeof (cache));
02379   cache[1] = x;
02380 
02381   result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
02382 
02383   /* If the original exponent was negative, reciprocate the result.  */
02384   if (n < 0)
02385     result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
02386          result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
02387 
02388   return result;
02389 }
02390 
02391 /* Expand a call to the pow built-in mathematical function.  Return 0 if
02392    a normal call should be emitted rather than expanding the function
02393    in-line.  EXP is the expression that is a call to the builtin
02394    function; if convenient, the result should be placed in TARGET.  */
02395 
02396 static rtx
02397 expand_builtin_pow (tree exp, rtx target, rtx subtarget)
02398 {
02399   tree arglist = TREE_OPERAND (exp, 1);
02400   tree arg0, arg1;
02401 
02402   if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
02403     return 0;
02404 
02405   arg0 = TREE_VALUE (arglist);
02406   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
02407 
02408   if (TREE_CODE (arg1) == REAL_CST
02409       && ! TREE_CONSTANT_OVERFLOW (arg1))
02410     {
02411       REAL_VALUE_TYPE cint;
02412       REAL_VALUE_TYPE c;
02413       HOST_WIDE_INT n;
02414 
02415       c = TREE_REAL_CST (arg1);
02416       n = real_to_integer (&c);
02417       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
02418       if (real_identical (&c, &cint))
02419   {
02420     /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
02421        Otherwise, check the number of multiplications required.
02422        Note that pow never sets errno for an integer exponent.  */
02423     if ((n >= -1 && n <= 2)
02424         || (flag_unsafe_math_optimizations
02425       && ! optimize_size
02426       && powi_cost (n) <= POWI_MAX_MULTS))
02427       {
02428         enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
02429         rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
02430         op = force_reg (mode, op);
02431         return expand_powi (op, mode, n);
02432       }
02433   }
02434     }
02435 
02436   if (! flag_unsafe_math_optimizations)
02437     return NULL_RTX;
02438   return expand_builtin_mathfn_2 (exp, target, subtarget);
02439 }
02440 
02441 /* Expand a call to the powi built-in mathematical function.  Return 0 if
02442    a normal call should be emitted rather than expanding the function
02443    in-line.  EXP is the expression that is a call to the builtin
02444    function; if convenient, the result should be placed in TARGET.  */
02445 
02446 static rtx
02447 expand_builtin_powi (tree exp, rtx target, rtx subtarget)
02448 {
02449   tree arglist = TREE_OPERAND (exp, 1);
02450   tree arg0, arg1;
02451   rtx op0, op1;
02452   enum machine_mode mode;
02453 
02454   if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
02455     return 0;
02456 
02457   arg0 = TREE_VALUE (arglist);
02458   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
02459   mode = TYPE_MODE (TREE_TYPE (exp));
02460 
02461   /* Handle constant power.  */
02462 
02463   if (TREE_CODE (arg1) == INTEGER_CST
02464       && ! TREE_CONSTANT_OVERFLOW (arg1))
02465     {
02466       HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
02467 
02468       /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
02469    Otherwise, check the number of multiplications required.  */
02470       if ((TREE_INT_CST_HIGH (arg1) == 0
02471      || TREE_INT_CST_HIGH (arg1) == -1)
02472     && ((n >= -1 && n <= 2)
02473         || (! optimize_size
02474       && powi_cost (n) <= POWI_MAX_MULTS)))
02475   {
02476     op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
02477     op0 = force_reg (mode, op0);
02478     return expand_powi (op0, mode, n);
02479   }
02480     }
02481 
02482   /* Emit a libcall to libgcc.  */
02483 
02484   if (target == NULL_RTX)
02485     target = gen_reg_rtx (mode);
02486 
02487   op0 = expand_expr (arg0, subtarget, mode, 0);
02488   if (GET_MODE (op0) != mode)
02489     op0 = convert_to_mode (mode, op0, 0);
02490   op1 = expand_expr (arg1, 0, word_mode, 0);
02491   if (GET_MODE (op1) != word_mode)
02492     op1 = convert_to_mode (word_mode, op1, 0);
02493 
02494   target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
02495             target, LCT_CONST_MAKE_BLOCK, mode, 2,
02496             op0, mode, op1, word_mode);
02497 
02498   return target;
02499 }
02500 
02501 /* Expand expression EXP which is a call to the strlen builtin.  Return 0
02502    if we failed the caller should emit a normal call, otherwise
02503    try to get the result in TARGET, if convenient.  */
02504 
02505 static rtx
02506 expand_builtin_strlen (tree arglist, rtx target,
02507            enum machine_mode target_mode)
02508 {
02509   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
02510     return 0;
02511   else
02512     {
02513       rtx pat;
02514       tree len, src = TREE_VALUE (arglist);
02515       rtx result, src_reg, char_rtx, before_strlen;
02516       enum machine_mode insn_mode = target_mode, char_mode;
02517       enum insn_code icode = CODE_FOR_nothing;
02518       int align;
02519 
02520       /* If the length can be computed at compile-time, return it.  */
02521       len = c_strlen (src, 0);
02522       if (len)
02523   return expand_expr (len, target, target_mode, EXPAND_NORMAL);
02524 
02525       /* If the length can be computed at compile-time and is constant
02526    integer, but there are side-effects in src, evaluate
02527    src for side-effects, then return len.
02528    E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
02529    can be optimized into: i++; x = 3;  */
02530       len = c_strlen (src, 1);
02531       if (len && TREE_CODE (len) == INTEGER_CST)
02532   {
02533     expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
02534     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
02535   }
02536 
02537       align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
02538 
02539       /* If SRC is not a pointer type, don't do this operation inline.  */
02540       if (align == 0)
02541   return 0;
02542 
02543       /* Bail out if we can't compute strlen in the right mode.  */
02544       while (insn_mode != VOIDmode)
02545   {
02546     icode = strlen_optab->handlers[(int) insn_mode].insn_code;
02547     if (icode != CODE_FOR_nothing)
02548       break;
02549 
02550     insn_mode = GET_MODE_WIDER_MODE (insn_mode);
02551   }
02552       if (insn_mode == VOIDmode)
02553   return 0;
02554 
02555       /* Make a place to write the result of the instruction.  */
02556       result = target;
02557       if (! (result != 0
02558        && REG_P (result)
02559        && GET_MODE (result) == insn_mode
02560        && REGNO (result) >= FIRST_PSEUDO_REGISTER))
02561   result = gen_reg_rtx (insn_mode);
02562 
02563       /* Make a place to hold the source address.  We will not expand
02564    the actual source until we are sure that the expansion will
02565    not fail -- there are trees that cannot be expanded twice.  */
02566       src_reg = gen_reg_rtx (Pmode);
02567 
02568       /* Mark the beginning of the strlen sequence so we can emit the
02569    source operand later.  */
02570       before_strlen = get_last_insn ();
02571 
02572       char_rtx = const0_rtx;
02573       char_mode = insn_data[(int) icode].operand[2].mode;
02574       if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
02575                   char_mode))
02576   char_rtx = copy_to_mode_reg (char_mode, char_rtx);
02577 
02578       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
02579            char_rtx, GEN_INT (align));
02580       if (! pat)
02581   return 0;
02582       emit_insn (pat);
02583 
02584       /* Now that we are assured of success, expand the source.  */
02585       start_sequence ();
02586       pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
02587       if (pat != src_reg)
02588   emit_move_insn (src_reg, pat);
02589       pat = get_insns ();
02590       end_sequence ();
02591 
02592       if (before_strlen)
02593   emit_insn_after (pat, before_strlen);
02594       else
02595   emit_insn_before (pat, get_insns ());
02596 
02597       /* Return the value in the proper mode for this function.  */
02598       if (GET_MODE (result) == target_mode)
02599   target = result;
02600       else if (target != 0)
02601   convert_move (target, result, 0);
02602       else
02603   target = convert_to_mode (target_mode, result, 0);
02604 
02605       return target;
02606     }
02607 }
02608 
02609 /* Expand a call to the strstr builtin.  Return 0 if we failed the
02610    caller should emit a normal call, otherwise try to get the result
02611    in TARGET, if convenient (and in mode MODE if that's convenient).  */
02612 
02613 static rtx
02614 expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
02615 {
02616   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
02617     {
02618       tree result = fold_builtin_strstr (arglist, type);
02619       if (result)
02620   return expand_expr (result, target, mode, EXPAND_NORMAL);
02621     }
02622   return 0;
02623 }
02624 
02625 /* Expand a call to the strchr builtin.  Return 0 if we failed the
02626    caller should emit a normal call, otherwise try to get the result
02627    in TARGET, if convenient (and in mode MODE if that's convenient).  */
02628 
02629 static rtx
02630 expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
02631 {
02632   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
02633     {
02634       tree result = fold_builtin_strchr (arglist, type);
02635       if (result)
02636   return expand_expr (result, target, mode, EXPAND_NORMAL);
02637 
02638       /* FIXME: Should use strchrM optab so that ports can optimize this.  */
02639     }
02640   return 0;
02641 }
02642 
02643 /* Expand a call to the strrchr builtin.  Return 0 if we failed the
02644    caller should emit a normal call, otherwise try to get the result
02645    in TARGET, if convenient (and in mode MODE if that's convenient).  */
02646 
02647 static rtx
02648 expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
02649 {
02650   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
02651     {
02652       tree result = fold_builtin_strrchr (arglist, type);
02653       if (result)
02654   return expand_expr (result, target, mode, EXPAND_NORMAL);
02655     }
02656   return 0;
02657 }
02658 
02659 /* Expand a call to the strpbrk builtin.  Return 0 if we failed the
02660    caller should emit a normal call, otherwise try to get the result
02661    in TARGET, if convenient (and in mode MODE if that's convenient).  */
02662 
02663 static rtx
02664 expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
02665 {
02666   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
02667     {
02668       tree result = fold_builtin_strpbrk (arglist, type);
02669       if (result)
02670   return expand_expr (result, target, mode, EXPAND_NORMAL);
02671     }
02672   return 0;
02673 }
02674 
02675 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
02676    bytes from constant string DATA + OFFSET and return it as target
02677    constant.  */
02678 
02679 static rtx
02680 builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
02681        enum machine_mode mode)
02682 {
02683   const char *str = (const char *) data;
02684 
02685   gcc_assert (offset >= 0
02686         && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
02687       <= strlen (str) + 1));
02688 
02689   return c_readstr (str + offset, mode);
02690 }
02691 
02692 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
02693    Return 0 if we failed, the caller should emit a normal call,
02694    otherwise try to get the result in TARGET, if convenient (and in
02695    mode MODE if that's convenient).  */
02696 static rtx
02697 expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
02698 {
02699   tree arglist = TREE_OPERAND (exp, 1);
02700   if (!validate_arglist (arglist,
02701        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
02702     return 0;
02703   else
02704     {
02705       tree dest = TREE_VALUE (arglist);
02706       tree src = TREE_VALUE (TREE_CHAIN (arglist));
02707       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
02708       const char *src_str;
02709       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
02710       unsigned int dest_align
02711   = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
02712       rtx dest_mem, src_mem, dest_addr, len_rtx;
02713       tree result = fold_builtin_memcpy (exp);
02714 
02715       if (result)
02716   return expand_expr (result, target, mode, EXPAND_NORMAL);
02717 
02718       /* If DEST is not a pointer type, call the normal function.  */
02719       if (dest_align == 0)
02720   return 0;
02721 
02722       /* If either SRC is not a pointer type, don't do this
02723          operation in-line.  */
02724       if (src_align == 0)
02725   return 0;
02726 
02727       dest_mem = get_memory_rtx (dest, len);
02728       set_mem_align (dest_mem, dest_align);
02729       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
02730       src_str = c_getstr (src);
02731 
02732       /* If SRC is a string constant and block move would be done
02733    by pieces, we can avoid loading the string from memory
02734    and only stored the computed constants.  */
02735       if (src_str
02736     && GET_CODE (len_rtx) == CONST_INT
02737     && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
02738     && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
02739           (void *) src_str, dest_align))
02740   {
02741     dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
02742               builtin_memcpy_read_str,
02743               (void *) src_str, dest_align, 0);
02744     dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
02745     dest_mem = convert_memory_address (ptr_mode, dest_mem);
02746     return dest_mem;
02747   }
02748 
02749       src_mem = get_memory_rtx (src, len);
02750       set_mem_align (src_mem, src_align);
02751 
02752       /* Copy word part most expediently.  */
02753       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
02754            CALL_EXPR_TAILCALL (exp)
02755            ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
02756 
02757       if (dest_addr == 0)
02758   {
02759     dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
02760     dest_addr = convert_memory_address (ptr_mode, dest_addr);
02761   }
02762       return dest_addr;
02763     }
02764 }
02765 
02766 /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
02767    Return 0 if we failed the caller should emit a normal call,
02768    otherwise try to get the result in TARGET, if convenient (and in
02769    mode MODE if that's convenient).  If ENDP is 0 return the
02770    destination pointer, if ENDP is 1 return the end pointer ala
02771    mempcpy, and if ENDP is 2 return the end pointer minus one ala
02772    stpcpy.  */
02773 
02774 static rtx
02775 expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
02776       int endp)
02777 {
02778   if (!validate_arglist (arglist,
02779        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
02780     return 0;
02781   /* If return value is ignored, transform mempcpy into memcpy.  */
02782   else if (target == const0_rtx)
02783     {
02784       tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
02785 
02786       if (!fn)
02787   return 0;
02788 
02789       return expand_expr (build_function_call_expr (fn, arglist),
02790         target, mode, EXPAND_NORMAL);
02791     }
02792   else
02793     {
02794       tree dest = TREE_VALUE (arglist);
02795       tree src = TREE_VALUE (TREE_CHAIN (arglist));
02796       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
02797       const char *src_str;
02798       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
02799       unsigned int dest_align
02800   = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
02801       rtx dest_mem, src_mem, len_rtx;
02802       tree result = fold_builtin_mempcpy (arglist, type, endp);
02803 
02804       if (result)
02805   return expand_expr (result, target, mode, EXPAND_NORMAL);
02806       
02807       /* If either SRC or DEST is not a pointer type, don't do this
02808          operation in-line.  */
02809       if (dest_align == 0 || src_align == 0)
02810   return 0;
02811 
02812       /* If LEN is not constant, call the normal function.  */
02813       if (! host_integerp (len, 1))
02814   return 0;
02815 
02816       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
02817       src_str = c_getstr (src);
02818 
02819       /* If SRC is a string constant and block move would be done
02820    by pieces, we can avoid loading the string from memory
02821    and only stored the computed constants.  */
02822       if (src_str
02823     && GET_CODE (len_rtx) == CONST_INT
02824     && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
02825     && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
02826           (void *) src_str, dest_align))
02827   {
02828     dest_mem = get_memory_rtx (dest, len);
02829     set_mem_align (dest_mem, dest_align);
02830     dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
02831               builtin_memcpy_read_str,
02832               (void *) src_str, dest_align, endp);
02833     dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
02834     dest_mem = convert_memory_address (ptr_mode, dest_mem);
02835     return dest_mem;
02836   }
02837 
02838       if (GET_CODE (len_rtx) == CONST_INT
02839     && can_move_by_pieces (INTVAL (len_rtx),
02840          MIN (dest_align, src_align)))
02841   {
02842     dest_mem = get_memory_rtx (dest, len);
02843     set_mem_align (dest_mem, dest_align);
02844     src_mem = get_memory_rtx (src, len);
02845     set_mem_align (src_mem, src_align);
02846     dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
02847              MIN (dest_align, src_align), endp);
02848     dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
02849     dest_mem = convert_memory_address (ptr_mode, dest_mem);
02850     return dest_mem;
02851   }
02852 
02853       return 0;
02854     }
02855 }
02856 
02857 /* Expand expression EXP, which is a call to the memmove builtin.  Return 0
02858    if we failed the caller should emit a normal call.  */
02859 
02860 static rtx
02861 expand_builtin_memmove (tree arglist, tree type, rtx target,
02862       enum machine_mode mode, tree orig_exp)
02863 {
02864   if (!validate_arglist (arglist,
02865        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
02866     return 0;
02867   else
02868     {
02869       tree dest = TREE_VALUE (arglist);
02870       tree src = TREE_VALUE (TREE_CHAIN (arglist));
02871       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
02872 
02873       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
02874       unsigned int dest_align
02875   = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
02876       tree result = fold_builtin_memmove (arglist, type);
02877 
02878       if (result)
02879   return expand_expr (result, target, mode, EXPAND_NORMAL);
02880 
02881       /* If DEST is not a pointer type, call the normal function.  */
02882       if (dest_align == 0)
02883   return 0;
02884 
02885       /* If either SRC is not a pointer type, don't do this
02886          operation in-line.  */
02887       if (src_align == 0)
02888   return 0;
02889 
02890       /* If src is categorized for a readonly section we can use
02891    normal memcpy.  */
02892       if (readonly_data_expr (src))
02893         {
02894     tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
02895     if (!fn)
02896       return 0;
02897     fn = build_function_call_expr (fn, arglist);
02898     if (TREE_CODE (fn) == CALL_EXPR)
02899       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
02900     return expand_expr (fn, target, mode, EXPAND_NORMAL);
02901   }
02902 
02903       /* If length is 1 and we can expand memcpy call inline,
02904    it is ok to use memcpy as well.  */
02905       if (integer_onep (len))
02906         {
02907     rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
02908               /*endp=*/0);
02909     if (ret)
02910       return ret;
02911         }
02912 
02913       /* Otherwise, call the normal function.  */
02914       return 0;
02915    }
02916 }
02917 
02918 /* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
02919    if we failed the caller should emit a normal call.  */
02920 
02921 static rtx
02922 expand_builtin_bcopy (tree exp)
02923 {
02924   tree arglist = TREE_OPERAND (exp, 1);
02925   tree type = TREE_TYPE (exp);
02926   tree src, dest, size, newarglist;
02927 
02928   if (!validate_arglist (arglist,
02929        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
02930     return NULL_RTX;
02931 
02932   src = TREE_VALUE (arglist);
02933   dest = TREE_VALUE (TREE_CHAIN (arglist));
02934   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
02935 
02936   /* New argument list transforming bcopy(ptr x, ptr y, int z) to
02937      memmove(ptr y, ptr x, size_t z).   This is done this way
02938      so that if it isn't expanded inline, we fallback to
02939      calling bcopy instead of memmove.  */
02940 
02941   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
02942   newarglist = tree_cons (NULL_TREE, src, newarglist);
02943   newarglist = tree_cons (NULL_TREE, dest, newarglist);
02944 
02945   return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
02946 }
02947 
02948 #ifndef HAVE_movstr
02949 # define HAVE_movstr 0
02950 # define CODE_FOR_movstr CODE_FOR_nothing
02951 #endif
02952 
02953 /* Expand into a movstr instruction, if one is available.  Return 0 if
02954    we failed, the caller should emit a normal call, otherwise try to
02955    get the result in TARGET, if convenient.  If ENDP is 0 return the
02956    destination pointer, if ENDP is 1 return the end pointer ala
02957    mempcpy, and if ENDP is 2 return the end pointer minus one ala
02958    stpcpy.  */
02959 
02960 static rtx
02961 expand_movstr (tree dest, tree src, rtx target, int endp)
02962 {
02963   rtx end;
02964   rtx dest_mem;
02965   rtx src_mem;
02966   rtx insn;
02967   const struct insn_data * data;
02968 
02969   if (!HAVE_movstr)
02970     return 0;
02971 
02972   dest_mem = get_memory_rtx (dest, NULL);
02973   src_mem = get_memory_rtx (src, NULL);
02974   if (!endp)
02975     {
02976       target = force_reg (Pmode, XEXP (dest_mem, 0));
02977       dest_mem = replace_equiv_address (dest_mem, target);
02978       end = gen_reg_rtx (Pmode);
02979     }
02980   else
02981     {
02982       if (target == 0 || target == const0_rtx)
02983   {
02984     end = gen_reg_rtx (Pmode);
02985     if (target == 0)
02986       target = end;
02987   }
02988       else
02989   end = target;
02990     }
02991 
02992   data = insn_data + CODE_FOR_movstr;
02993 
02994   if (data->operand[0].mode != VOIDmode)
02995     end = gen_lowpart (data->operand[0].mode, end);
02996 
02997   insn = data->genfun (end, dest_mem, src_mem);
02998 
02999   gcc_assert (insn);
03000 
03001   emit_insn (insn);
03002 
03003   /* movstr is supposed to set end to the address of the NUL
03004      terminator.  If the caller requested a mempcpy-like return value,
03005      adjust it.  */
03006   if (endp == 1 && target != const0_rtx)
03007     {
03008       rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
03009       emit_move_insn (target, force_operand (tem, NULL_RTX));
03010     }
03011 
03012   return target;
03013 }
03014 
03015 /* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
03016    if we failed the caller should emit a normal call, otherwise try to get
03017    the result in TARGET, if convenient (and in mode MODE if that's
03018    convenient).  */
03019 
03020 static rtx
03021 expand_builtin_strcpy (tree exp, rtx target, enum machine_mode mode)
03022 {
03023   tree arglist = TREE_OPERAND (exp, 1);
03024   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
03025     {
03026       tree result = fold_builtin_strcpy (exp, 0);
03027       if (result)
03028   return expand_expr (result, target, mode, EXPAND_NORMAL);
03029 
03030       return expand_movstr (TREE_VALUE (arglist),
03031           TREE_VALUE (TREE_CHAIN (arglist)),
03032           target, /*endp=*/0);
03033     }
03034   return 0;
03035 }
03036 
03037 /* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
03038    Return 0 if we failed the caller should emit a normal call,
03039    otherwise try to get the result in TARGET, if convenient (and in
03040    mode MODE if that's convenient).  */
03041 
03042 static rtx
03043 expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
03044 {
03045   tree arglist = TREE_OPERAND (exp, 1);
03046   /* If return value is ignored, transform stpcpy into strcpy.  */
03047   if (target == const0_rtx)
03048     {
03049       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
03050       if (!fn)
03051   return 0;
03052 
03053       return expand_expr (build_function_call_expr (fn, arglist),
03054         target, mode, EXPAND_NORMAL);
03055     }
03056 
03057   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
03058     return 0;
03059   else
03060     {
03061       tree dst, src, len, lenp1;
03062       tree narglist;
03063       rtx ret;
03064 
03065       /* Ensure we get an actual string whose length can be evaluated at
03066          compile-time, not an expression containing a string.  This is
03067          because the latter will potentially produce pessimized code
03068          when used to produce the return value.  */
03069       src = TREE_VALUE (TREE_CHAIN (arglist));
03070       if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
03071   return expand_movstr (TREE_VALUE (arglist),
03072             TREE_VALUE (TREE_CHAIN (arglist)),
03073             target, /*endp=*/2);
03074 
03075       dst = TREE_VALUE (arglist);
03076       lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
03077       narglist = build_tree_list (NULL_TREE, lenp1);
03078       narglist = tree_cons (NULL_TREE, src, narglist);
03079       narglist = tree_cons (NULL_TREE, dst, narglist);
03080       ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
03081             target, mode, /*endp=*/2);
03082 
03083       if (ret)
03084   return ret;
03085 
03086       if (TREE_CODE (len) == INTEGER_CST)
03087   {
03088     rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
03089 
03090     if (GET_CODE (len_rtx) == CONST_INT)
03091       {
03092         ret = expand_builtin_strcpy (exp, target, mode);
03093 
03094         if (ret)
03095     {
03096       if (! target)
03097         {
03098           if (mode != VOIDmode)
03099       target = gen_reg_rtx (mode);
03100           else
03101       target = gen_reg_rtx (GET_MODE (ret));
03102         }
03103       if (GET_MODE (target) != GET_MODE (ret))
03104         ret = gen_lowpart (GET_MODE (target), ret);
03105 
03106       ret = plus_constant (ret, INTVAL (len_rtx));
03107       ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
03108       gcc_assert (ret);
03109 
03110       return target;
03111     }
03112       }
03113   }
03114 
03115       return expand_movstr (TREE_VALUE (arglist),
03116           TREE_VALUE (TREE_CHAIN (arglist)),
03117           target, /*endp=*/2);
03118     }
03119 }
03120 
03121 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
03122    bytes from constant string DATA + OFFSET and return it as target
03123    constant.  */
03124 
03125 static rtx
03126 builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
03127         enum machine_mode mode)
03128 {
03129   const char *str = (const char *) data;
03130 
03131   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
03132     return const0_rtx;
03133 
03134   return c_readstr (str + offset, mode);
03135 }
03136 
03137 /* Expand expression EXP, which is a call to the strncpy builtin.  Return 0
03138    if we failed the caller should emit a normal call.  */
03139 
03140 static rtx
03141 expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
03142 {
03143   tree arglist = TREE_OPERAND (exp, 1);
03144   if (validate_arglist (arglist,
03145       POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
03146     {
03147       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
03148       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03149       tree result = fold_builtin_strncpy (exp, slen);
03150       
03151       if (result)
03152   return expand_expr (result, target, mode, EXPAND_NORMAL);
03153 
03154       /* We must be passed a constant len and src parameter.  */
03155       if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
03156   return 0;
03157 
03158       slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
03159 
03160       /* We're required to pad with trailing zeros if the requested
03161          len is greater than strlen(s2)+1.  In that case try to
03162    use store_by_pieces, if it fails, punt.  */
03163       if (tree_int_cst_lt (slen, len))
03164   {
03165     tree dest = TREE_VALUE (arglist);
03166     unsigned int dest_align
03167       = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
03168     const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
03169     rtx dest_mem;
03170 
03171     if (!p || dest_align == 0 || !host_integerp (len, 1)
03172         || !can_store_by_pieces (tree_low_cst (len, 1),
03173                builtin_strncpy_read_str,
03174                (void *) p, dest_align))
03175       return 0;
03176 
03177     dest_mem = get_memory_rtx (dest, len);
03178     store_by_pieces (dest_mem, tree_low_cst (len, 1),
03179          builtin_strncpy_read_str,
03180          (void *) p, dest_align, 0);
03181     dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
03182     dest_mem = convert_memory_address (ptr_mode, dest_mem);
03183     return dest_mem;
03184   }
03185     }
03186   return 0;
03187 }
03188 
03189 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
03190    bytes from constant string DATA + OFFSET and return it as target
03191    constant.  */
03192 
03193 static rtx
03194 builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
03195        enum machine_mode mode)
03196 {
03197   const char *c = (const char *) data;
03198   char *p = alloca (GET_MODE_SIZE (mode));
03199 
03200   memset (p, *c, GET_MODE_SIZE (mode));
03201 
03202   return c_readstr (p, mode);
03203 }
03204 
03205 /* Callback routine for store_by_pieces.  Return the RTL of a register
03206    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
03207    char value given in the RTL register data.  For example, if mode is
03208    4 bytes wide, return the RTL for 0x01010101*data.  */
03209 
03210 static rtx
03211 builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
03212       enum machine_mode mode)
03213 {
03214   rtx target, coeff;
03215   size_t size;
03216   char *p;
03217 
03218   size = GET_MODE_SIZE (mode);
03219   if (size == 1)
03220     return (rtx) data;
03221 
03222   p = alloca (size);
03223   memset (p, 1, size);
03224   coeff = c_readstr (p, mode);
03225 
03226   target = convert_to_mode (mode, (rtx) data, 1);
03227   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
03228   return force_reg (mode, target);
03229 }
03230 
03231 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
03232    if we failed the caller should emit a normal call, otherwise try to get
03233    the result in TARGET, if convenient (and in mode MODE if that's
03234    convenient).  */
03235 
03236 static rtx
03237 expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
03238            tree orig_exp)
03239 {
03240   if (!validate_arglist (arglist,
03241        POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
03242     return 0;
03243   else
03244     {
03245       tree dest = TREE_VALUE (arglist);
03246       tree val = TREE_VALUE (TREE_CHAIN (arglist));
03247       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03248       char c;
03249 
03250       unsigned int dest_align
03251   = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
03252       rtx dest_mem, dest_addr, len_rtx;
03253 
03254       /* If DEST is not a pointer type, don't do this
03255    operation in-line.  */
03256       if (dest_align == 0)
03257   return 0;
03258 
03259       /* If the LEN parameter is zero, return DEST.  */
03260       if (integer_zerop (len))
03261   {
03262     /* Evaluate and ignore VAL in case it has side-effects.  */
03263     expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
03264     return expand_expr (dest, target, mode, EXPAND_NORMAL);
03265   }
03266 
03267       if (TREE_CODE (val) != INTEGER_CST)
03268   {
03269     rtx val_rtx;
03270 
03271     if (!host_integerp (len, 1))
03272       return 0;
03273 
03274     if (optimize_size && tree_low_cst (len, 1) > 1)
03275       return 0;
03276 
03277     /* Assume that we can memset by pieces if we can store the
03278      * the coefficients by pieces (in the required modes).
03279      * We can't pass builtin_memset_gen_str as that emits RTL.  */
03280     c = 1;
03281     if (!can_store_by_pieces (tree_low_cst (len, 1),
03282             builtin_memset_read_str,
03283             &c, dest_align))
03284       return 0;
03285 
03286     val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
03287     val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
03288     val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
03289              val_rtx);
03290     dest_mem = get_memory_rtx (dest, len);
03291     store_by_pieces (dest_mem, tree_low_cst (len, 1),
03292          builtin_memset_gen_str,
03293          val_rtx, dest_align, 0);
03294     dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
03295     dest_mem = convert_memory_address (ptr_mode, dest_mem);
03296     return dest_mem;
03297   }
03298 
03299       if (target_char_cast (val, &c))
03300   return 0;
03301 
03302       if (c)
03303   {
03304     if (!host_integerp (len, 1))
03305       return 0;
03306     if (!can_store_by_pieces (tree_low_cst (len, 1),
03307             builtin_memset_read_str, &c,
03308             dest_align))
03309       return 0;
03310 
03311     dest_mem = get_memory_rtx (dest, len);
03312     store_by_pieces (dest_mem, tree_low_cst (len, 1),
03313          builtin_memset_read_str,
03314          &c, dest_align, 0);
03315     dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
03316     dest_mem = convert_memory_address (ptr_mode, dest_mem);
03317     return dest_mem;
03318   }
03319 
03320       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
03321 
03322       dest_mem = get_memory_rtx (dest, len);
03323       set_mem_align (dest_mem, dest_align);
03324       dest_addr = clear_storage (dest_mem, len_rtx,
03325          CALL_EXPR_TAILCALL (orig_exp)
03326          ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
03327 
03328       if (dest_addr == 0)
03329   {
03330     dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
03331     dest_addr = convert_memory_address (ptr_mode, dest_addr);
03332   }
03333 
03334       return dest_addr;
03335     }
03336 }
03337 
03338 /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
03339    if we failed the caller should emit a normal call.  */
03340 
03341 static rtx
03342 expand_builtin_bzero (tree exp)
03343 {
03344   tree arglist = TREE_OPERAND (exp, 1);
03345   tree dest, size, newarglist;
03346 
03347   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
03348     return NULL_RTX;
03349 
03350   dest = TREE_VALUE (arglist);
03351   size = TREE_VALUE (TREE_CHAIN (arglist));
03352 
03353   /* New argument list transforming bzero(ptr x, int y) to
03354      memset(ptr x, int 0, size_t y).   This is done this way
03355      so that if it isn't expanded inline, we fallback to
03356      calling bzero instead of memset.  */
03357 
03358   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
03359   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
03360   newarglist = tree_cons (NULL_TREE, dest, newarglist);
03361 
03362   return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
03363 }
03364 
03365 /* Expand expression EXP, which is a call to the memcmp built-in function.
03366    ARGLIST is the argument list for this call.  Return 0 if we failed and the
03367    caller should emit a normal call, otherwise try to get the result in
03368    TARGET, if convenient (and in mode MODE, if that's convenient).  */
03369 
03370 static rtx
03371 expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
03372            enum machine_mode mode)
03373 {
03374   if (!validate_arglist (arglist,
03375        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
03376     return 0;
03377   else
03378     {
03379       tree result = fold_builtin_memcmp (arglist);
03380       if (result)
03381   return expand_expr (result, target, mode, EXPAND_NORMAL);
03382     }
03383 
03384 #if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi
03385   {
03386     tree arg1 = TREE_VALUE (arglist);
03387     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
03388     tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03389     rtx arg1_rtx, arg2_rtx, arg3_rtx;
03390     rtx result;
03391     rtx insn;
03392 
03393     int arg1_align
03394       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
03395     int arg2_align
03396       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
03397     enum machine_mode insn_mode;
03398 
03399 #ifdef HAVE_cmpmemsi
03400     if (HAVE_cmpmemsi)
03401       insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
03402     else
03403 #endif
03404 #ifdef HAVE_cmpstrsi
03405     if (HAVE_cmpstrsi)
03406       insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
03407     else
03408 #endif
03409       return 0;
03410 
03411     /* If we don't have POINTER_TYPE, call the function.  */
03412     if (arg1_align == 0 || arg2_align == 0)
03413       return 0;
03414 
03415     /* Make a place to write the result of the instruction.  */
03416     result = target;
03417     if (! (result != 0
03418      && REG_P (result) && GET_MODE (result) == insn_mode
03419      && REGNO (result) >= FIRST_PSEUDO_REGISTER))
03420       result = gen_reg_rtx (insn_mode);
03421 
03422     arg1_rtx = get_memory_rtx (arg1, len);
03423     arg2_rtx = get_memory_rtx (arg2, len);
03424     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
03425 
03426     /* Set MEM_SIZE as appropriate.  */
03427     if (GET_CODE (arg3_rtx) == CONST_INT)
03428       {
03429   set_mem_size (arg1_rtx, arg3_rtx);
03430   set_mem_size (arg2_rtx, arg3_rtx);
03431       }
03432 
03433 #ifdef HAVE_cmpmemsi
03434     if (HAVE_cmpmemsi)
03435       insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
03436          GEN_INT (MIN (arg1_align, arg2_align)));
03437     else
03438 #endif
03439 #ifdef HAVE_cmpstrsi
03440     if (HAVE_cmpstrsi)
03441       insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
03442          GEN_INT (MIN (arg1_align, arg2_align)));
03443     else
03444 #endif
03445       gcc_unreachable ();
03446 
03447     if (insn)
03448       emit_insn (insn);
03449     else
03450       emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
03451              TYPE_MODE (integer_type_node), 3,
03452              XEXP (arg1_rtx, 0), Pmode,
03453              XEXP (arg2_rtx, 0), Pmode,
03454              convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
03455             TYPE_UNSIGNED (sizetype)),
03456              TYPE_MODE (sizetype));
03457 
03458     /* Return the value in the proper mode for this function.  */
03459     mode = TYPE_MODE (TREE_TYPE (exp));
03460     if (GET_MODE (result) == mode)
03461       return result;
03462     else if (target != 0)
03463       {
03464   convert_move (target, result, 0);
03465   return target;
03466       }
03467     else
03468       return convert_to_mode (mode, result, 0);
03469   }
03470 #endif
03471 
03472   return 0;
03473 }
03474 
03475 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
03476    if we failed the caller should emit a normal call, otherwise try to get
03477    the result in TARGET, if convenient.  */
03478 
03479 static rtx
03480 expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
03481 {
03482   tree arglist = TREE_OPERAND (exp, 1);
03483 
03484   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
03485     return 0;
03486   else
03487     {
03488       tree result = fold_builtin_strcmp (arglist);
03489       if (result)
03490   return expand_expr (result, target, mode, EXPAND_NORMAL);
03491     }
03492 
03493 #ifdef HAVE_cmpstrsi
03494   if (HAVE_cmpstrsi)
03495   {
03496     tree arg1 = TREE_VALUE (arglist);
03497     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
03498     tree len, len1, len2;
03499     rtx arg1_rtx, arg2_rtx, arg3_rtx;
03500     rtx result, insn;
03501     tree fndecl, fn;
03502 
03503     int arg1_align
03504       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
03505     int arg2_align
03506       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
03507     enum machine_mode insn_mode
03508       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
03509 
03510     len1 = c_strlen (arg1, 1);
03511     len2 = c_strlen (arg2, 1);
03512 
03513     if (len1)
03514       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
03515     if (len2)
03516       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
03517 
03518     /* If we don't have a constant length for the first, use the length
03519        of the second, if we know it.  We don't require a constant for
03520        this case; some cost analysis could be done if both are available
03521        but neither is constant.  For now, assume they're equally cheap,
03522        unless one has side effects.  If both strings have constant lengths,
03523        use the smaller.  */
03524 
03525     if (!len1)
03526       len = len2;
03527     else if (!len2)
03528       len = len1;
03529     else if (TREE_SIDE_EFFECTS (len1))
03530       len = len2;
03531     else if (TREE_SIDE_EFFECTS (len2))
03532       len = len1;
03533     else if (TREE_CODE (len1) != INTEGER_CST)
03534       len = len2;
03535     else if (TREE_CODE (len2) != INTEGER_CST)
03536       len = len1;
03537     else if (tree_int_cst_lt (len1, len2))
03538       len = len1;
03539     else
03540       len = len2;
03541 
03542     /* If both arguments have side effects, we cannot optimize.  */
03543     if (!len || TREE_SIDE_EFFECTS (len))
03544       return 0;
03545 
03546     /* If we don't have POINTER_TYPE, call the function.  */
03547     if (arg1_align == 0 || arg2_align == 0)
03548       return 0;
03549 
03550     /* Make a place to write the result of the instruction.  */
03551     result = target;
03552     if (! (result != 0
03553      && REG_P (result) && GET_MODE (result) == insn_mode
03554      && REGNO (result) >= FIRST_PSEUDO_REGISTER))
03555       result = gen_reg_rtx (insn_mode);
03556 
03557     /* Stabilize the arguments in case gen_cmpstrsi fails.  */
03558     arg1 = builtin_save_expr (arg1);
03559     arg2 = builtin_save_expr (arg2);
03560 
03561     arg1_rtx = get_memory_rtx (arg1, NULL);
03562     arg2_rtx = get_memory_rtx (arg2, NULL);
03563     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
03564     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
03565        GEN_INT (MIN (arg1_align, arg2_align)));
03566     if (insn)
03567       {
03568   emit_insn (insn);
03569 
03570   /* Return the value in the proper mode for this function.  */
03571   mode = TYPE_MODE (TREE_TYPE (exp));
03572   if (GET_MODE (result) == mode)
03573     return result;
03574   if (target == 0)
03575     return convert_to_mode (mode, result, 0);
03576   convert_move (target, result, 0);
03577   return target;
03578       }
03579 
03580     /* Expand the library call ourselves using a stabilized argument
03581        list to avoid re-evaluating the function's arguments twice.  */
03582     arglist = build_tree_list (NULL_TREE, arg2);
03583     arglist = tree_cons (NULL_TREE, arg1, arglist);
03584     fndecl = get_callee_fndecl (exp);
03585     fn = build_function_call_expr (fndecl, arglist);
03586     if (TREE_CODE (fn) == CALL_EXPR)
03587       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
03588     return expand_call (fn, target, target == const0_rtx);
03589   }
03590 #endif
03591   return 0;
03592 }
03593 
03594 /* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
03595    if we failed the caller should emit a normal call, otherwise try to get
03596    the result in TARGET, if convenient.  */
03597 
03598 static rtx
03599 expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
03600 {
03601   tree arglist = TREE_OPERAND (exp, 1);
03602 
03603   if (!validate_arglist (arglist,
03604        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
03605     return 0;
03606   else
03607     {
03608       tree result = fold_builtin_strncmp (arglist);
03609       if (result)
03610   return expand_expr (result, target, mode, EXPAND_NORMAL);
03611     }
03612 
03613   /* If c_strlen can determine an expression for one of the string
03614      lengths, and it doesn't have side effects, then emit cmpstrsi
03615      using length MIN(strlen(string)+1, arg3).  */
03616 #ifdef HAVE_cmpstrsi
03617   if (HAVE_cmpstrsi)
03618   {
03619     tree arg1 = TREE_VALUE (arglist);
03620     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
03621     tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03622     tree len, len1, len2;
03623     rtx arg1_rtx, arg2_rtx, arg3_rtx;
03624     rtx result, insn;
03625     tree fndecl, fn;
03626 
03627     int arg1_align
03628       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
03629     int arg2_align
03630       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
03631     enum machine_mode insn_mode
03632       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
03633 
03634     len1 = c_strlen (arg1, 1);
03635     len2 = c_strlen (arg2, 1);
03636 
03637     if (len1)
03638       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
03639     if (len2)
03640       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
03641 
03642     /* If we don't have a constant length for the first, use the length
03643        of the second, if we know it.  We don't require a constant for
03644        this case; some cost analysis could be done if both are available
03645        but neither is constant.  For now, assume they're equally cheap,
03646        unless one has side effects.  If both strings have constant lengths,
03647        use the smaller.  */
03648 
03649     if (!len1)
03650       len = len2;
03651     else if (!len2)
03652       len = len1;
03653     else if (TREE_SIDE_EFFECTS (len1))
03654       len = len2;
03655     else if (TREE_SIDE_EFFECTS (len2))
03656       len = len1;
03657     else if (TREE_CODE (len1) != INTEGER_CST)
03658       len = len2;
03659     else if (TREE_CODE (len2) != INTEGER_CST)
03660       len = len1;
03661     else if (tree_int_cst_lt (len1, len2))
03662       len = len1;
03663     else
03664       len = len2;
03665 
03666     /* If both arguments have side effects, we cannot optimize.  */
03667     if (!len || TREE_SIDE_EFFECTS (len))
03668       return 0;
03669 
03670     /* The actual new length parameter is MIN(len,arg3).  */
03671     len = fold (build2 (MIN_EXPR, TREE_TYPE (len), len,
03672       fold_convert (TREE_TYPE (len), arg3)));
03673 
03674     /* If we don't have POINTER_TYPE, call the function.  */
03675     if (arg1_align == 0 || arg2_align == 0)
03676       return 0;
03677 
03678     /* Make a place to write the result of the instruction.  */
03679     result = target;
03680     if (! (result != 0
03681      && REG_P (result) && GET_MODE (result) == insn_mode
03682      && REGNO (result) >= FIRST_PSEUDO_REGISTER))
03683       result = gen_reg_rtx (insn_mode);
03684 
03685     /* Stabilize the arguments in case gen_cmpstrsi fails.  */
03686     arg1 = builtin_save_expr (arg1);
03687     arg2 = builtin_save_expr (arg2);
03688     len = builtin_save_expr (len);
03689 
03690     arg1_rtx = get_memory_rtx (arg1, len);
03691     arg2_rtx = get_memory_rtx (arg2, len);
03692     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
03693     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
03694        GEN_INT (MIN (arg1_align, arg2_align)));
03695     if (insn)
03696       {
03697   emit_insn (insn);
03698 
03699   /* Return the value in the proper mode for this function.  */
03700   mode = TYPE_MODE (TREE_TYPE (exp));
03701   if (GET_MODE (result) == mode)
03702     return result;
03703   if (target == 0)
03704     return convert_to_mode (mode, result, 0);
03705   convert_move (target, result, 0);
03706   return target;
03707       }
03708 
03709     /* Expand the library call ourselves using a stabilized argument
03710        list to avoid re-evaluating the function's arguments twice.  */
03711     arglist = build_tree_list (NULL_TREE, len);
03712     arglist = tree_cons (NULL_TREE, arg2, arglist);
03713     arglist = tree_cons (NULL_TREE, arg1, arglist);
03714     fndecl = get_callee_fndecl (exp);
03715     fn = build_function_call_expr (fndecl, arglist);
03716     if (TREE_CODE (fn) == CALL_EXPR)
03717       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
03718     return expand_call (fn, target, target == const0_rtx);
03719   }
03720 #endif
03721   return 0;
03722 }
03723 
03724 /* Expand expression EXP, which is a call to the strcat builtin.
03725    Return 0 if we failed the caller should emit a normal call,
03726    otherwise try to get the result in TARGET, if convenient.  */
03727 
03728 static rtx
03729 expand_builtin_strcat (tree arglist, tree type, rtx target, enum machine_mode mode)
03730 {
03731   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
03732     return 0;
03733   else
03734     {
03735       tree dst = TREE_VALUE (arglist),
03736   src = TREE_VALUE (TREE_CHAIN (arglist));
03737       const char *p = c_getstr (src);
03738 
03739       if (p)
03740   {
03741     /* If the string length is zero, return the dst parameter.  */
03742     if (*p == '\0')
03743       return expand_expr (dst, target, mode, EXPAND_NORMAL);
03744     else if (!optimize_size)
03745       {
03746         /* Otherwise if !optimize_size, see if we can store by
03747                  pieces into (dst + strlen(dst)).  */
03748         tree newdst, arglist,
03749     strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
03750 
03751         /* This is the length argument.  */
03752         arglist = build_tree_list (NULL_TREE,
03753            fold (size_binop (PLUS_EXPR,
03754                  c_strlen (src, 0),
03755                  ssize_int (1))));
03756         /* Prepend src argument.  */
03757         arglist = tree_cons (NULL_TREE, src, arglist);
03758 
03759         /* We're going to use dst more than once.  */
03760         dst = builtin_save_expr (dst);
03761 
03762         /* Create strlen (dst).  */
03763         newdst =
03764     fold (build_function_call_expr (strlen_fn,
03765             build_tree_list (NULL_TREE,
03766                  dst)));
03767         /* Create (dst + strlen (dst)).  */
03768         newdst = fold (build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
03769 
03770         /* Prepend the new dst argument.  */
03771         arglist = tree_cons (NULL_TREE, newdst, arglist);
03772 
03773         /* We don't want to get turned into a memcpy if the
03774                  target is const0_rtx, i.e. when the return value
03775                  isn't used.  That would produce pessimized code so
03776                  pass in a target of zero, it should never actually be
03777                  used.  If this was successful return the original
03778                  dst, not the result of mempcpy.  */
03779         if (expand_builtin_mempcpy (arglist, type, /*target=*/0, mode, /*endp=*/0))
03780     return expand_expr (dst, target, mode, EXPAND_NORMAL);
03781         else
03782     return 0;
03783       }
03784   }
03785 
03786       return 0;
03787     }
03788 }
03789 
03790 /* Expand expression EXP, which is a call to the strncat builtin.
03791    Return 0 if we failed the caller should emit a normal call,
03792    otherwise try to get the result in TARGET, if convenient.  */
03793 
03794 static rtx
03795 expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
03796 {
03797   if (validate_arglist (arglist,
03798       POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
03799     {
03800       tree result = fold_builtin_strncat (arglist);
03801       if (result)
03802   return expand_expr (result, target, mode, EXPAND_NORMAL);
03803     }
03804   return 0;
03805 }
03806 
03807 /* Expand expression EXP, which is a call to the strspn builtin.
03808    Return 0 if we failed the caller should emit a normal call,
03809    otherwise try to get the result in TARGET, if convenient.  */
03810 
03811 static rtx
03812 expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
03813 {
03814   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
03815     {
03816       tree result = fold_builtin_strspn (arglist);
03817       if (result)
03818   return expand_expr (result, target, mode, EXPAND_NORMAL);
03819     }
03820   return 0;
03821 }
03822 
03823 /* Expand expression EXP, which is a call to the strcspn builtin.
03824    Return 0 if we failed the caller should emit a normal call,
03825    otherwise try to get the result in TARGET, if convenient.  */
03826 
03827 static rtx
03828 expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
03829 {
03830   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
03831     {
03832       tree result = fold_builtin_strcspn (arglist);
03833       if (result)
03834   return expand_expr (result, target, mode, EXPAND_NORMAL);
03835     }
03836   return 0;
03837 }
03838 
03839 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
03840    if that's convenient.  */
03841 
03842 rtx
03843 expand_builtin_saveregs (void)
03844 {
03845   rtx val, seq;
03846 
03847   /* Don't do __builtin_saveregs more than once in a function.
03848      Save the result of the first call and reuse it.  */
03849   if (saveregs_value != 0)
03850     return saveregs_value;
03851 
03852   /* When this function is called, it means that registers must be
03853      saved on entry to this function.  So we migrate the call to the
03854      first insn of this function.  */
03855 
03856   start_sequence ();
03857 
03858   /* Do whatever the machine needs done in this case.  */
03859   val = targetm.calls.expand_builtin_saveregs ();
03860 
03861   seq = get_insns ();
03862   end_sequence ();
03863 
03864   saveregs_value = val;
03865 
03866   /* Put the insns after the NOTE that starts the function.  If this
03867      is inside a start_sequence, make the outer-level insn chain current, so
03868      the code is placed at the start of the function.  */
03869   push_topmost_sequence ();
03870   emit_insn_after (seq, entry_of_function ());
03871   pop_topmost_sequence ();
03872 
03873   return val;
03874 }
03875 
03876 /* __builtin_args_info (N) returns word N of the arg space info
03877    for the current function.  The number and meanings of words
03878    is controlled by the definition of CUMULATIVE_ARGS.  */
03879 
03880 static rtx
03881 expand_builtin_args_info (tree arglist)
03882 {
03883   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
03884   int *word_ptr = (int *) &current_function_args_info;
03885 
03886   gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
03887 
03888   if (arglist != 0)
03889     {
03890       if (!host_integerp (TREE_VALUE (arglist), 0))
03891   error ("argument of %<__builtin_args_info%> must be constant");
03892       else
03893   {
03894     HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
03895 
03896     if (wordnum < 0 || wordnum >= nwords)
03897       error ("argument of %<__builtin_args_info%> out of range");
03898     else
03899       return GEN_INT (word_ptr[wordnum]);
03900   }
03901     }
03902   else
03903     error ("missing argument in %<__builtin_args_info%>");
03904 
03905   return const0_rtx;
03906 }
03907 
03908 /* Expand a call to __builtin_next_arg.  */
03909 
03910 static rtx
03911 expand_builtin_next_arg (void)
03912 {
03913   /* Checking arguments is already done in fold_builtin_next_arg
03914      that must be called before this function.  */
03915   return expand_binop (Pmode, add_optab,
03916            current_function_internal_arg_pointer,
03917            current_function_arg_offset_rtx,
03918            NULL_RTX, 0, OPTAB_LIB_WIDEN);
03919 }
03920 
03921 /* Make it easier for the backends by protecting the valist argument
03922    from multiple evaluations.  */
03923 
03924 static tree
03925 stabilize_va_list (tree valist, int needs_lvalue)
03926 {
03927   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
03928     {
03929       if (TREE_SIDE_EFFECTS (valist))
03930   valist = save_expr (valist);
03931 
03932       /* For this case, the backends will be expecting a pointer to
03933    TREE_TYPE (va_list_type_node), but it's possible we've
03934    actually been given an array (an actual va_list_type_node).
03935    So fix it.  */
03936       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
03937   {
03938     tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
03939     valist = build_fold_addr_expr_with_type (valist, p1);
03940   }
03941     }
03942   else
03943     {
03944       tree pt;
03945 
03946       if (! needs_lvalue)
03947   {
03948     if (! TREE_SIDE_EFFECTS (valist))
03949       return valist;
03950 
03951     pt = build_pointer_type (va_list_type_node);
03952     valist = fold (build1 (ADDR_EXPR, pt, valist));
03953     TREE_SIDE_EFFECTS (valist) = 1;
03954   }
03955 
03956       if (TREE_SIDE_EFFECTS (valist))
03957   valist = save_expr (valist);
03958       valist = build_fold_indirect_ref (valist);
03959     }
03960 
03961   return valist;
03962 }
03963 
03964 /* The "standard" definition of va_list is void*.  */
03965 
03966 tree
03967 std_build_builtin_va_list (void)
03968 {
03969   return ptr_type_node;
03970 }
03971 
03972 /* The "standard" implementation of va_start: just assign `nextarg' to
03973    the variable.  */
03974 
03975 void
03976 std_expand_builtin_va_start (tree valist, rtx nextarg)
03977 {
03978   tree t;
03979 
03980   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
03981         make_tree (ptr_type_node, nextarg));
03982   TREE_SIDE_EFFECTS (t) = 1;
03983 
03984   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03985 }
03986 
03987 /* Expand ARGLIST, from a call to __builtin_va_start.  */
03988 
03989 static rtx
03990 expand_builtin_va_start (tree arglist)
03991 {
03992   rtx nextarg;
03993   tree chain, valist;
03994 
03995   chain = TREE_CHAIN (arglist);
03996 
03997   if (!chain)
03998     {
03999       error ("too few arguments to function %<va_start%>");
04000       return const0_rtx;
04001     }
04002 
04003   if (fold_builtin_next_arg (chain))
04004     return const0_rtx;
04005 
04006   nextarg = expand_builtin_next_arg ();
04007   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
04008 
04009 #ifdef EXPAND_BUILTIN_VA_START
04010   EXPAND_BUILTIN_VA_START (valist, nextarg);
04011 #else
04012   std_expand_builtin_va_start (valist, nextarg);
04013 #endif
04014 
04015   return const0_rtx;
04016 }
04017 
04018 /* The "standard" implementation of va_arg: read the value from the
04019    current (padded) address and increment by the (padded) size.  */
04020 
04021 tree
04022 std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
04023 {
04024   tree addr, t, type_size, rounded_size, valist_tmp;
04025   unsigned HOST_WIDE_INT align, boundary;
04026   bool indirect;
04027 
04028 #ifdef ARGS_GROW_DOWNWARD
04029   /* All of the alignment and movement below is for args-grow-up machines.
04030      As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
04031      implement their own specialized gimplify_va_arg_expr routines.  */
04032   gcc_unreachable ();
04033 #endif
04034 
04035   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
04036   if (indirect)
04037     type = build_pointer_type (type);
04038 
04039   align = PARM_BOUNDARY / BITS_PER_UNIT;
04040   boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
04041 
04042   /* Hoist the valist value into a temporary for the moment.  */
04043   valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
04044 
04045   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
04046      requires greater alignment, we must perform dynamic alignment.  */
04047   if (boundary > align)
04048     {
04049       t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
04050       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
04051       build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
04052       gimplify_and_add (t, pre_p);
04053 
04054       t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
04055       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
04056       build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
04057       gimplify_and_add (t, pre_p);
04058     }
04059   else
04060     boundary = align;
04061 
04062   /* If the actual alignment is less than the alignment of the type,
04063      adjust the type accordingly so that we don't assume strict alignment
04064      when deferencing the pointer.  */
04065   boundary *= BITS_PER_UNIT;
04066   if (boundary < TYPE_ALIGN (type))
04067     {
04068       type = build_variant_type_copy (type);
04069       TYPE_ALIGN (type) = boundary;
04070     }
04071 
04072   /* Compute the rounded size of the type.  */
04073   type_size = size_in_bytes (type);
04074   rounded_size = round_up (type_size, align);
04075 
04076   /* Reduce rounded_size so it's sharable with the postqueue.  */
04077   gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
04078 
04079   /* Get AP.  */
04080   addr = valist_tmp;
04081   if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
04082     {
04083       /* Small args are padded downward.  */
04084       t = fold (build2 (GT_EXPR, sizetype, rounded_size, size_int (align)));
04085       t = fold (build3 (COND_EXPR, sizetype, t, size_zero_node,
04086       size_binop (MINUS_EXPR, rounded_size, type_size)));
04087       t = fold_convert (TREE_TYPE (addr), t);
04088       addr = fold (build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t));
04089     }
04090 
04091   /* Compute new value for AP.  */
04092   t = fold_convert (TREE_TYPE (valist), rounded_size);
04093   t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
04094   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
04095   gimplify_and_add (t, pre_p);
04096 
04097   addr = fold_convert (build_pointer_type (type), addr);
04098 
04099   if (indirect)
04100     addr = build_va_arg_indirect_ref (addr);
04101 
04102   return build_va_arg_indirect_ref (addr);
04103 }
04104 
04105 /* Build an indirect-ref expression over the given TREE, which represents a
04106    piece of a va_arg() expansion.  */
04107 tree
04108 build_va_arg_indirect_ref (tree addr)
04109 {
04110   addr = build_fold_indirect_ref (addr);
04111 
04112   if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF.  */
04113     mf_mark (addr);
04114 
04115   return addr;
04116 }
04117 
04118 /* Return a dummy expression of type TYPE in order to keep going after an
04119    error.  */
04120 
04121 static tree
04122 dummy_object (tree type)
04123 {
04124   tree t = convert (build_pointer_type (type), null_pointer_node);
04125   return build1 (INDIRECT_REF, type, t);
04126 }
04127 
04128 /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
04129    builtin function, but a very special sort of operator.  */
04130 
04131 enum gimplify_status
04132 gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
04133 {
04134   tree promoted_type, want_va_type, have_va_type;
04135   tree valist = TREE_OPERAND (*expr_p, 0);
04136   tree type = TREE_TYPE (*expr_p);
04137   tree t;
04138 
04139   /* Verify that valist is of the proper type.  */
04140   want_va_type = va_list_type_node;
04141   have_va_type = TREE_TYPE (valist);
04142 
04143   if (have_va_type == error_mark_node)
04144     return GS_ERROR;
04145 
04146   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
04147     {
04148       /* If va_list is an array type, the argument may have decayed
04149    to a pointer type, e.g. by being passed to another function.
04150          In that case, unwrap both types so that we can compare the
04151    underlying records.  */
04152       if (TREE_CODE (have_va_type) == ARRAY_TYPE
04153     || POINTER_TYPE_P (have_va_type))
04154   {
04155     want_va_type = TREE_TYPE (want_va_type);
04156     have_va_type = TREE_TYPE (have_va_type);
04157   }
04158     }
04159 
04160   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
04161     {
04162       error ("first argument to %<va_arg%> not of type %<va_list%>");
04163       return GS_ERROR;
04164     }
04165 
04166   /* Generate a diagnostic for requesting data of a type that cannot
04167      be passed through `...' due to type promotion at the call site.  */
04168   else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
04169      != type)
04170     {
04171       static bool gave_help;
04172 
04173       /* Unfortunately, this is merely undefined, rather than a constraint
04174    violation, so we cannot make this an error.  If this call is never
04175    executed, the program is still strictly conforming.  */
04176       warning ("%qT is promoted to %qT when passed through %<...%>",
04177          type, promoted_type);
04178       if (! gave_help)
04179   {
04180     gave_help = true;
04181     warning ("(so you should pass %qT not %qT to %<va_arg%>)",
04182        promoted_type, type);
04183   }
04184 
04185       /* We can, however, treat "undefined" any way we please.
04186    Call abort to encourage the user to fix the program.  */
04187       inform ("if this code is reached, the program will abort");
04188       t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
04189             NULL);
04190       append_to_statement_list (t, pre_p);
04191 
04192       /* This is dead code, but go ahead and finish so that the
04193    mode of the result comes out right.  */
04194       *expr_p = dummy_object (type);
04195       return GS_ALL_DONE;
04196     }
04197   else
04198     {
04199       /* Make it easier for the backends by protecting the valist argument
04200          from multiple evaluations.  */
04201       if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
04202   {
04203     /* For this case, the backends will be expecting a pointer to
04204        TREE_TYPE (va_list_type_node), but it's possible we've
04205        actually been given an array (an actual va_list_type_node).
04206        So fix it.  */
04207     if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
04208       {
04209         tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
04210         valist = build_fold_addr_expr_with_type (valist, p1);
04211       }
04212     gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
04213   }
04214       else
04215   gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
04216 
04217       if (!targetm.gimplify_va_arg_expr)
04218   /* Once most targets are converted this should abort.  */
04219   return GS_ALL_DONE;
04220 
04221       *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
04222       return GS_OK;
04223     }
04224 }
04225 
04226 /* Expand ARGLIST, from a call to __builtin_va_end.  */
04227 
04228 static rtx
04229 expand_builtin_va_end (tree arglist)
04230 {
04231   tree valist = TREE_VALUE (arglist);
04232 
04233   /* Evaluate for side effects, if needed.  I hate macros that don't
04234      do that.  */
04235   if (TREE_SIDE_EFFECTS (valist))
04236     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
04237 
04238   return const0_rtx;
04239 }
04240 
04241 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
04242    builtin rather than just as an assignment in stdarg.h because of the
04243    nastiness of array-type va_list types.  */
04244 
04245 static rtx
04246 expand_builtin_va_copy (tree arglist)
04247 {
04248   tree dst, src, t;
04249 
04250   dst = TREE_VALUE (arglist);
04251   src = TREE_VALUE (TREE_CHAIN (arglist));
04252 
04253   dst = stabilize_va_list (dst, 1);
04254   src = stabilize_va_list (src, 0);
04255 
04256   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
04257     {
04258       t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
04259       TREE_SIDE_EFFECTS (t) = 1;
04260       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04261     }
04262   else
04263     {
04264       rtx dstb, srcb, size;
04265 
04266       /* Evaluate to pointers.  */
04267       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
04268       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
04269       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
04270         VOIDmode, EXPAND_NORMAL);
04271 
04272       dstb = convert_memory_address (Pmode, dstb);
04273       srcb = convert_memory_address (Pmode, srcb);
04274 
04275       /* "Dereference" to BLKmode memories.  */
04276       dstb = gen_rtx_MEM (BLKmode, dstb);
04277       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
04278       set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
04279       srcb = gen_rtx_MEM (BLKmode, srcb);
04280       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
04281       set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
04282 
04283       /* Copy.  */
04284       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
04285     }
04286 
04287   return const0_rtx;
04288 }
04289 
04290 /* Expand a call to one of the builtin functions __builtin_frame_address or
04291    __builtin_return_address.  */
04292 
04293 static rtx
04294 expand_builtin_frame_address (tree fndecl, tree arglist)
04295 {
04296   /* The argument must be a nonnegative integer constant.
04297      It counts the number of frames to scan up the stack.
04298      The value is the return address saved in that frame.  */
04299   if (arglist == 0)
04300     /* Warning about missing arg was already issued.  */
04301     return const0_rtx;
04302   else if (! host_integerp (TREE_VALUE (arglist), 1))
04303     {
04304       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
04305   error ("invalid argument to %<__builtin_frame_address%>");
04306       else
04307   error ("invalid argument to %<__builtin_return_address%>");
04308       return const0_rtx;
04309     }
04310   else
04311     {
04312       rtx tem
04313   = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
04314               tree_low_cst (TREE_VALUE (arglist), 1));
04315 
04316       /* Some ports cannot access arbitrary stack frames.  */
04317       if (tem == NULL)
04318   {
04319     if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
04320       warning ("unsupported argument to %<__builtin_frame_address%>");
04321     else
04322       warning ("unsupported argument to %<__builtin_return_address%>");
04323     return const0_rtx;
04324   }
04325 
04326       /* For __builtin_frame_address, return what we've got.  */
04327       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
04328   return tem;
04329 
04330       if (!REG_P (tem)
04331     && ! CONSTANT_P (tem))
04332   tem = copy_to_mode_reg (Pmode, tem);
04333       return tem;
04334     }
04335 }
04336 
04337 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
04338    we failed and the caller should emit a normal call, otherwise try to get
04339    the result in TARGET, if convenient.  */
04340 
04341 static rtx
04342 expand_builtin_alloca (tree arglist, rtx target)
04343 {
04344   rtx op0;
04345   rtx result;
04346 
04347   /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
04348      should always expand to function calls.  These can be intercepted
04349      in libmudflap.  */
04350   if (flag_mudflap)
04351     return 0;
04352 
04353   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
04354     return 0;
04355 
04356   /* Compute the argument.  */
04357   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
04358 
04359   /* Allocate the desired space.  */
04360   result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
04361   result = convert_memory_address (ptr_mode, result);
04362 
04363   return result;
04364 }
04365 
04366 /* Expand a call to a unary builtin.  The arguments are in ARGLIST.
04367    Return 0 if a normal call should be emitted rather than expanding the
04368    function in-line.  If convenient, the result should be placed in TARGET.
04369    SUBTARGET may be used as the target for computing one of EXP's operands.  */
04370 
04371 static rtx
04372 expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
04373          rtx subtarget, optab op_optab)
04374 {
04375   rtx op0;
04376   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
04377     return 0;
04378 
04379   /* Compute the argument.  */
04380   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
04381   /* Compute op, into TARGET if possible.
04382      Set TARGET to wherever the result comes back.  */
04383   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
04384       op_optab, op0, target, 1);
04385   gcc_assert (target);
04386 
04387   return convert_to_mode (target_mode, target, 0);
04388 }
04389 
04390 /* If the string passed to fputs is a constant and is one character
04391    long, we attempt to transform this call into __builtin_fputc().  */
04392 
04393 static rtx
04394 expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
04395 {
04396   /* Verify the arguments in the original call.  */
04397   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
04398     {
04399       tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
04400           unlocked, NULL_TREE);
04401       if (result)
04402   return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
04403     }
04404   return 0;
04405 }
04406 
04407 /* Expand a call to __builtin_expect.  We return our argument and emit a
04408    NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
04409    a non-jump context.  */
04410 
04411 static rtx
04412 expand_builtin_expect (tree arglist, rtx target)
04413 {
04414   tree exp, c;
04415   rtx note, rtx_c;
04416 
04417   if (arglist == NULL_TREE
04418       || TREE_CHAIN (arglist) == NULL_TREE)
04419     return const0_rtx;
04420   exp = TREE_VALUE (arglist);
04421   c = TREE_VALUE (TREE_CHAIN (arglist));
04422 
04423   if (TREE_CODE (c) != INTEGER_CST)
04424     {
04425       error ("second argument to %<__builtin_expect%> must be a constant");
04426       c = integer_zero_node;
04427     }
04428 
04429   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
04430 
04431   /* Don't bother with expected value notes for integral constants.  */
04432   if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
04433     {
04434       /* We do need to force this into a register so that we can be
04435    moderately sure to be able to correctly interpret the branch
04436    condition later.  */
04437       target = force_reg (GET_MODE (target), target);
04438 
04439       rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
04440 
04441       note = emit_note (NOTE_INSN_EXPECTED_VALUE);
04442       NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
04443     }
04444 
04445   return target;
04446 }
04447 
04448 /* Like expand_builtin_expect, except do this in a jump context.  This is
04449    called from do_jump if the conditional is a __builtin_expect.  Return either
04450    a list of insns to emit the jump or NULL if we cannot optimize
04451    __builtin_expect.  We need to optimize this at jump time so that machines
04452    like the PowerPC don't turn the test into a SCC operation, and then jump
04453    based on the test being 0/1.  */
04454 
04455 rtx
04456 expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
04457 {
04458   tree arglist = TREE_OPERAND (exp, 1);
04459   tree arg0 = TREE_VALUE (arglist);
04460   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
04461   rtx ret = NULL_RTX;
04462 
04463   /* Only handle __builtin_expect (test, 0) and
04464      __builtin_expect (test, 1).  */
04465   if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
04466       && (integer_zerop (arg1) || integer_onep (arg1)))
04467     {
04468       rtx insn, drop_through_label, temp;
04469 
04470       /* Expand the jump insns.  */
04471       start_sequence ();
04472       do_jump (arg0, if_false_label, if_true_label);
04473       ret = get_insns ();
04474 
04475       drop_through_label = get_last_insn ();
04476       if (drop_through_label && NOTE_P (drop_through_label))
04477   drop_through_label = prev_nonnote_insn (drop_through_label);
04478       if (drop_through_label && !LABEL_P (drop_through_label))
04479   drop_through_label = NULL_RTX;
04480       end_sequence ();
04481 
04482       if (! if_true_label)
04483   if_true_label = drop_through_label;
04484       if (! if_false_label)
04485   if_false_label = drop_through_label;
04486 
04487       /* Go through and add the expect's to each of the conditional jumps.  */
04488       insn = ret;
04489       while (insn != NULL_RTX)
04490   {
04491     rtx next = NEXT_INSN (insn);
04492 
04493     if (JUMP_P (insn) && any_condjump_p (insn))
04494       {
04495         rtx ifelse = SET_SRC (pc_set (insn));
04496         rtx then_dest = XEXP (ifelse, 1);
04497         rtx else_dest = XEXP (ifelse, 2);
04498         int taken = -1;
04499 
04500         /* First check if we recognize any of the labels.  */
04501         if (GET_CODE (then_dest) == LABEL_REF
04502       && XEXP (then_dest, 0) == if_true_label)
04503     taken = 1;
04504         else if (GET_CODE (then_dest) == LABEL_REF
04505            && XEXP (then_dest, 0) == if_false_label)
04506     taken = 0;
04507         else if (GET_CODE (else_dest) == LABEL_REF
04508            && XEXP (else_dest, 0) == if_false_label)
04509     taken = 1;
04510         else if (GET_CODE (else_dest) == LABEL_REF
04511            && XEXP (else_dest, 0) == if_true_label)
04512     taken = 0;
04513         /* Otherwise check where we drop through.  */
04514         else if (else_dest == pc_rtx)
04515     {
04516       if (next && NOTE_P (next))
04517         next = next_nonnote_insn (next);
04518 
04519       if (next && JUMP_P (next)
04520           && any_uncondjump_p (next))
04521         temp = XEXP (SET_SRC (pc_set (next)), 0);
04522       else
04523         temp = next;
04524 
04525       /* TEMP is either a CODE_LABEL, NULL_RTX or something
04526          else that can't possibly match either target label.  */
04527       if (temp == if_false_label)
04528         taken = 1;
04529       else if (temp == if_true_label)
04530         taken = 0;
04531     }
04532         else if (then_dest == pc_rtx)
04533     {
04534       if (next && NOTE_P (next))
04535         next = next_nonnote_insn (next);
04536 
04537       if (next && JUMP_P (next)
04538           && any_uncondjump_p (next))
04539         temp = XEXP (SET_SRC (pc_set (next)), 0);
04540       else
04541         temp = next;
04542 
04543       if (temp == if_false_label)
04544         taken = 0;
04545       else if (temp == if_true_label)
04546         taken = 1;
04547     }
04548 
04549         if (taken != -1)
04550     {
04551       /* If the test is expected to fail, reverse the
04552          probabilities.  */
04553       if (integer_zerop (arg1))
04554         taken = 1 - taken;
04555             predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
04556     }
04557       }
04558 
04559     insn = next;
04560   }
04561     }
04562 
04563   return ret;
04564 }
04565 
04566 static void
04567 expand_builtin_trap (void)
04568 {
04569 #ifdef HAVE_trap
04570   if (HAVE_trap)
04571     emit_insn (gen_trap ());
04572   else
04573 #endif
04574     emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
04575   emit_barrier ();
04576 }
04577 
04578 /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
04579    Return 0 if a normal call should be emitted rather than expanding
04580    the function inline.  If convenient, the result should be placed
04581    in TARGET.  SUBTARGET may be used as the target for computing
04582    the operand.  */
04583 
04584 static rtx
04585 expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
04586 {
04587   enum machine_mode mode;
04588   tree arg;
04589   rtx op0;
04590 
04591   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
04592     return 0;
04593 
04594   arg = TREE_VALUE (arglist);
04595   mode = TYPE_MODE (TREE_TYPE (arg));
04596   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
04597   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
04598 }
04599 
04600 /* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
04601    Return NULL is a normal call should be emitted rather than expanding the
04602    function inline.  If convenient, the result should be placed in TARGET.
04603    SUBTARGET may be used as the target for computing the operand.  */
04604 
04605 static rtx
04606 expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
04607 {
04608   rtx op0, op1;
04609   tree arg;
04610 
04611   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
04612     return 0;
04613 
04614   arg = TREE_VALUE (arglist);
04615   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
04616 
04617   arg = TREE_VALUE (TREE_CHAIN (arglist));
04618   op1 = expand_expr (arg, NULL, VOIDmode, 0);
04619 
04620   return expand_copysign (op0, op1, target);
04621 }
04622 
04623 /* Create a new constant string literal and return a char* pointer to it.
04624    The STRING_CST value is the LEN characters at STR.  */
04625 static tree
04626 build_string_literal (int len, const char *str)
04627 {
04628   tree t, elem, index, type;
04629 
04630   t = build_string (len, str);
04631   elem = build_type_variant (char_type_node, 1, 0);
04632   index = build_index_type (build_int_cst (NULL_TREE, len - 1));
04633   type = build_array_type (elem, index);
04634   TREE_TYPE (t) = type;
04635   TREE_CONSTANT (t) = 1;
04636   TREE_INVARIANT (t) = 1;
04637   TREE_READONLY (t) = 1;
04638   TREE_STATIC (t) = 1;
04639 
04640   type = build_pointer_type (type);
04641   t = build1 (ADDR_EXPR, type, t);
04642 
04643   type = build_pointer_type (elem);
04644   t = build1 (NOP_EXPR, type, t);
04645   return t;
04646 }
04647 
04648 /* Expand EXP, a call to printf or printf_unlocked.
04649    Return 0 if a normal call should be emitted rather than transforming
04650    the function inline.  If convenient, the result should be placed in
04651    TARGET with mode MODE.  UNLOCKED indicates this is a printf_unlocked
04652    call.  */
04653 static rtx
04654 expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
04655            bool unlocked)
04656 {
04657   tree arglist = TREE_OPERAND (exp, 1);
04658   tree fn_putchar = unlocked
04659         ? implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
04660         : implicit_built_in_decls[BUILT_IN_PUTCHAR];
04661   tree fn_puts = unlocked ? implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED]
04662         : implicit_built_in_decls[BUILT_IN_PUTS];
04663   const char *fmt_str;
04664   tree fn, fmt, arg;
04665 
04666   /* If the return value is used, don't do the transformation.  */
04667   if (target != const0_rtx)
04668     return 0;
04669 
04670   /* Verify the required arguments in the original call.  */
04671   if (! arglist)
04672     return 0;
04673   fmt = TREE_VALUE (arglist);
04674   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
04675     return 0;
04676   arglist = TREE_CHAIN (arglist);
04677 
04678   /* Check whether the format is a literal string constant.  */
04679   fmt_str = c_getstr (fmt);
04680   if (fmt_str == NULL)
04681     return 0;
04682 
04683   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
04684   if (strcmp (fmt_str, "%s\n") == 0)
04685     {
04686       if (! arglist
04687           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
04688     || TREE_CHAIN (arglist))
04689   return 0;
04690       fn = fn_puts;
04691     }
04692   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
04693   else if (strcmp (fmt_str, "%c") == 0)
04694     {
04695       if (! arglist
04696     || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
04697     || TREE_CHAIN (arglist))
04698   return 0;
04699       fn = fn_putchar;
04700     }
04701   else
04702     {
04703       /* We can't handle anything else with % args or %% ... yet.  */
04704       if (strchr (fmt_str, '%'))
04705         return 0;
04706 
04707       if (arglist)
04708   return 0;
04709 
04710       /* If the format specifier was "", printf does nothing.  */
04711       if (fmt_str[0] == '\0')
04712   return const0_rtx;
04713       /* If the format specifier has length of 1, call putchar.  */
04714       if (fmt_str[1] == '\0')
04715   {
04716     /* Given printf("c"), (where c is any one character,)
04717        convert "c"[0] to an int and pass that to the replacement
04718        function.  */
04719     arg = build_int_cst (NULL_TREE, fmt_str[0]);
04720     arglist = build_tree_list (NULL_TREE, arg);
04721     fn = fn_putchar;
04722   }
04723       else
04724   {
04725     /* If the format specifier was "string\n", call puts("string").  */
04726     size_t len = strlen (fmt_str);
04727     if (fmt_str[len - 1] == '\n')
04728       {
04729         /* Create a NUL-terminated string that's one char shorter
04730      than the original, stripping off the trailing '\n'.  */
04731         char *newstr = alloca (len);
04732         memcpy (newstr, fmt_str, len - 1);
04733         newstr[len - 1] = 0;
04734 
04735         arg = build_string_literal (len, newstr);
04736         arglist = build_tree_list (NULL_TREE, arg);
04737         fn = fn_puts;
04738       }
04739     else
04740       /* We'd like to arrange to call fputs(string,stdout) here,
04741          but we need stdout and don't have a way to get it yet.  */
04742       return 0;
04743   }
04744     }
04745 
04746   if (!fn)
04747     return 0;
04748   fn = build_function_call_expr (fn, arglist);
04749   if (TREE_CODE (fn) == CALL_EXPR)
04750     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
04751   return expand_expr (fn, target, mode, EXPAND_NORMAL);
04752 }
04753 
04754 /* Expand EXP, a call to fprintf or fprintf_unlocked.
04755    Return 0 if a normal call should be emitted rather than transforming
04756    the function inline.  If convenient, the result should be placed in
04757    TARGET with mode MODE.  UNLOCKED indicates this is a fprintf_unlocked
04758    call.  */
04759 static rtx
04760 expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
04761             bool unlocked)
04762 {
04763   tree arglist = TREE_OPERAND (exp, 1);
04764   tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
04765          : implicit_built_in_decls[BUILT_IN_FPUTC];
04766   tree fn_fputs = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
04767          : implicit_built_in_decls[BUILT_IN_FPUTS];
04768   const char *fmt_str;
04769   tree fn, fmt, fp, arg;
04770 
04771   /* If the return value is used, don't do the transformation.  */
04772   if (target != const0_rtx)
04773     return 0;
04774 
04775   /* Verify the required arguments in the original call.  */
04776   if (! arglist)
04777     return 0;
04778   fp = TREE_VALUE (arglist);
04779   if (! POINTER_TYPE_P (TREE_TYPE (fp)))
04780     return 0;
04781   arglist = TREE_CHAIN (arglist);
04782   if (! arglist)
04783     return 0;
04784   fmt = TREE_VALUE (arglist);
04785   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
04786     return 0;
04787   arglist = TREE_CHAIN (arglist);
04788 
04789   /* Check whether the format is a literal string constant.  */
04790   fmt_str = c_getstr (fmt);
04791   if (fmt_str == NULL)
04792     return 0;
04793 
04794   /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
04795   if (strcmp (fmt_str, "%s") == 0)
04796     {
04797       if (! arglist
04798           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
04799     || TREE_CHAIN (arglist))
04800   return 0;
04801       arg = TREE_VALUE (arglist);
04802       arglist = build_tree_list (NULL_TREE, fp);
04803       arglist = tree_cons (NULL_TREE, arg, arglist);
04804       fn = fn_fputs;
04805     }
04806   /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
04807   else if (strcmp (fmt_str, "%c") == 0)
04808     {
04809       if (! arglist
04810     || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
04811     || TREE_CHAIN (arglist))
04812   return 0;
04813       arg = TREE_VALUE (arglist);
04814       arglist = build_tree_list (NULL_TREE, fp);
04815       arglist = tree_cons (NULL_TREE, arg, arglist);
04816       fn = fn_fputc;
04817     }
04818   else
04819     {
04820       /* We can't handle anything else with % args or %% ... yet.  */
04821       if (strchr (fmt_str, '%'))
04822         return 0;
04823 
04824       if (arglist)
04825   return 0;
04826 
04827       /* If the format specifier was "", fprintf does nothing.  */
04828       if (fmt_str[0] == '\0')
04829   {
04830     /* Evaluate and ignore FILE* argument for side-effects.  */
04831     expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
04832     return const0_rtx;
04833   }
04834 
04835       /* When "string" doesn't contain %, replace all cases of
04836    fprintf(stream,string) with fputs(string,stream).  The fputs
04837    builtin will take care of special cases like length == 1.  */
04838       arglist = build_tree_list (NULL_TREE, fp);
04839       arglist = tree_cons (NULL_TREE, fmt, arglist);
04840       fn = fn_fputs;
04841     }
04842 
04843   if (!fn)
04844     return 0;
04845   fn = build_function_call_expr (fn, arglist);
04846   if (TREE_CODE (fn) == CALL_EXPR)
04847     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
04848   return expand_expr (fn, target, mode, EXPAND_NORMAL);
04849 }
04850 
04851 /* Expand a call to sprintf with argument list ARGLIST.  Return 0 if
04852    a normal call should be emitted rather than expanding the function
04853    inline.  If convenient, the result should be placed in TARGET with
04854    mode MODE.  */
04855 
04856 static rtx
04857 expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
04858 {
04859   tree orig_arglist, dest, fmt;
04860   const char *fmt_str;
04861 
04862   orig_arglist = arglist;
04863 
04864   /* Verify the required arguments in the original call.  */
04865   if (! arglist)
04866     return 0;
04867   dest = TREE_VALUE (arglist);
04868   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
04869     return 0;
04870   arglist = TREE_CHAIN (arglist);
04871   if (! arglist)
04872     return 0;
04873   fmt = TREE_VALUE (arglist);
04874   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
04875     return 0;
04876   arglist = TREE_CHAIN (arglist);
04877 
04878   /* Check whether the format is a literal string constant.  */
04879   fmt_str = c_getstr (fmt);
04880   if (fmt_str == NULL)
04881     return 0;
04882 
04883   /* If the format doesn't contain % args or %%, use strcpy.  */
04884   if (strchr (fmt_str, '%') == 0)
04885     {
04886       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
04887       tree exp;
04888 
04889       if (arglist || ! fn)
04890   return 0;
04891       expand_expr (build_function_call_expr (fn, orig_arglist),
04892        const0_rtx, VOIDmode, EXPAND_NORMAL);
04893       if (target == const0_rtx)
04894   return const0_rtx;
04895       exp = build_int_cst (NULL_TREE, strlen (fmt_str));
04896       return expand_expr (exp, target, mode, EXPAND_NORMAL);
04897     }
04898   /* If the format is "%s", use strcpy if the result isn't used.  */
04899   else if (strcmp (fmt_str, "%s") == 0)
04900     {
04901       tree fn, arg, len;
04902       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
04903 
04904       if (! fn)
04905   return 0;
04906 
04907       if (! arglist || TREE_CHAIN (arglist))
04908   return 0;
04909       arg = TREE_VALUE (arglist);
04910       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
04911   return 0;
04912 
04913       if (target != const0_rtx)
04914   {
04915     len = c_strlen (arg, 1);
04916     if (! len || TREE_CODE (len) != INTEGER_CST)
04917       return 0;
04918   }
04919       else
04920   len = NULL_TREE;
04921 
04922       arglist = build_tree_list (NULL_TREE, arg);
04923       arglist = tree_cons (NULL_TREE, dest, arglist);
04924       expand_expr (build_function_call_expr (fn, arglist),
04925        const0_rtx, VOIDmode, EXPAND_NORMAL);
04926 
04927       if (target == const0_rtx)
04928   return const0_rtx;
04929       return expand_expr (len, target, mode, EXPAND_NORMAL);
04930     }
04931 
04932   return 0;
04933 }
04934 
04935 /* Expand a call to either the entry or exit function profiler.  */
04936 
04937 static rtx
04938 expand_builtin_profile_func (bool exitp)
04939 {
04940   rtx this, which;
04941 
04942   this = DECL_RTL (current_function_decl);
04943   gcc_assert (MEM_P (this));
04944   this = XEXP (this, 0);
04945 
04946   if (exitp)
04947     which = profile_function_exit_libfunc;
04948   else
04949     which = profile_function_entry_libfunc;
04950 
04951   emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
04952          expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
04953              0),
04954          Pmode);
04955 
04956   return const0_rtx;
04957 }
04958 
04959 /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
04960 
04961 static rtx
04962 round_trampoline_addr (rtx tramp)
04963 {
04964   rtx temp, addend, mask;
04965 
04966   /* If we don't need too much alignment, we'll have been guaranteed
04967      proper alignment by get_trampoline_type.  */
04968   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
04969     return tramp;
04970 
04971   /* Round address up to desired boundary.  */
04972   temp = gen_reg_rtx (Pmode);
04973   addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
04974   mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
04975 
04976   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
04977              temp, 0, OPTAB_LIB_WIDEN);
04978   tramp = expand_simple_binop (Pmode, AND, temp, mask,
04979              temp, 0, OPTAB_LIB_WIDEN);
04980 
04981   return tramp;
04982 }
04983 
04984 static rtx
04985 expand_builtin_init_trampoline (tree arglist)
04986 {
04987   tree t_tramp, t_func, t_chain;
04988   rtx r_tramp, r_func, r_chain;
04989 #ifdef TRAMPOLINE_TEMPLATE
04990   rtx blktramp;
04991 #endif
04992 
04993   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
04994        POINTER_TYPE, VOID_TYPE))
04995     return NULL_RTX;
04996 
04997   t_tramp = TREE_VALUE (arglist);
04998   arglist = TREE_CHAIN (arglist);
04999   t_func = TREE_VALUE (arglist);
05000   arglist = TREE_CHAIN (arglist);
05001   t_chain = TREE_VALUE (arglist);
05002 
05003   r_tramp = expand_expr (t_tramp, NULL_RTX, VOIDmode, 0);
05004   r_func = expand_expr (t_func, NULL_RTX, VOIDmode, 0);
05005   r_chain = expand_expr (t_chain, NULL_RTX, VOIDmode, 0);
05006 
05007   /* Generate insns to initialize the trampoline.  */
05008   r_tramp = round_trampoline_addr (r_tramp);
05009 #ifdef TRAMPOLINE_TEMPLATE
05010   blktramp = gen_rtx_MEM (BLKmode, r_tramp);
05011   set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
05012   emit_block_move (blktramp, assemble_trampoline_template (),
05013        GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
05014 #endif
05015   trampolines_created = 1;
05016   INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
05017 
05018   return const0_rtx;
05019 }
05020 
05021 static rtx
05022 expand_builtin_adjust_trampoline (tree arglist)
05023 {
05024   rtx tramp;
05025 
05026   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
05027     return NULL_RTX;
05028 
05029   tramp = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
05030   tramp = round_trampoline_addr (tramp);
05031 #ifdef TRAMPOLINE_ADJUST_ADDRESS
05032   TRAMPOLINE_ADJUST_ADDRESS (tramp);
05033 #endif
05034 
05035   return tramp;
05036 }
05037 
05038 /* Expand a call to the built-in signbit, signbitf or signbitl function.
05039    Return NULL_RTX if a normal call should be emitted rather than expanding
05040    the function in-line.  EXP is the expression that is a call to the builtin
05041    function; if convenient, the result should be placed in TARGET.  */
05042 
05043 static rtx
05044 expand_builtin_signbit (tree exp, rtx target)
05045 {
05046   const struct real_format *fmt;
05047   enum machine_mode fmode, imode, rmode;
05048   HOST_WIDE_INT hi, lo;
05049   tree arg, arglist;
05050   int bitpos;
05051   rtx temp;
05052 
05053   arglist = TREE_OPERAND (exp, 1);
05054   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
05055     return 0;
05056 
05057   arg = TREE_VALUE (arglist);
05058   fmode = TYPE_MODE (TREE_TYPE (arg));
05059   rmode = TYPE_MODE (TREE_TYPE (exp));
05060   fmt = REAL_MODE_FORMAT (fmode);
05061 
05062   /* For floating point formats without a sign bit, implement signbit
05063      as "ARG < 0.0".  */
05064   if (fmt->signbit < 0)
05065   {
05066     /* But we can't do this if the format supports signed zero.  */
05067     if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
05068       return 0;
05069 
05070     arg = fold (build2 (LT_EXPR, TREE_TYPE (exp), arg,
05071       build_real (TREE_TYPE (arg), dconst0)));
05072     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
05073   }
05074 
05075   imode = int_mode_for_mode (fmode);
05076   if (imode == BLKmode)
05077     return 0;
05078 
05079   bitpos = fmt->signbit;
05080   /* Handle targets with different FP word orders.  */
05081   if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
05082     {
05083       int nwords = GET_MODE_BITSIZE (fmode) / BITS_PER_WORD;
05084       int word = nwords - (bitpos / BITS_PER_WORD) - 1;
05085       bitpos = word * BITS_PER_WORD + bitpos % BITS_PER_WORD;
05086     }
05087 
05088   /* If the sign bit is not in the lowpart and the floating point format
05089      is wider than an integer, check that is twice the size of an integer
05090      so that we can use gen_highpart below.  */
05091   if (bitpos >= GET_MODE_BITSIZE (rmode)
05092       && GET_MODE_BITSIZE (imode) != 2 * GET_MODE_BITSIZE (rmode))
05093     return 0;
05094 
05095   temp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
05096   temp = gen_lowpart (imode, temp);
05097 
05098   if (GET_MODE_BITSIZE (imode) > GET_MODE_BITSIZE (rmode))
05099     {
05100       if (BYTES_BIG_ENDIAN)
05101   bitpos = GET_MODE_BITSIZE (imode) - 1 - bitpos;
05102       temp = copy_to_mode_reg (imode, temp);
05103       temp = extract_bit_field (temp, 1, bitpos, 1,
05104         NULL_RTX, rmode, rmode);
05105     }
05106   else
05107     {
05108       if (GET_MODE_BITSIZE (imode) < GET_MODE_BITSIZE (rmode))
05109   temp = gen_lowpart (rmode, temp);
05110       if (bitpos < HOST_BITS_PER_WIDE_INT)
05111   {
05112     hi = 0;
05113     lo = (HOST_WIDE_INT) 1 << bitpos;
05114   }
05115       else
05116   {
05117     hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
05118     lo = 0;
05119   }
05120 
05121       temp = force_reg (rmode, temp);
05122       temp = expand_binop (rmode, and_optab, temp,
05123          immed_double_const (lo, hi, rmode),
05124          target, 1, OPTAB_LIB_WIDEN);
05125     }
05126   return temp;
05127 }
05128 
05129 /* Expand fork or exec calls.  TARGET is the desired target of the
05130    call.  ARGLIST is the list of arguments of the call.  FN is the
05131    identificator of the actual function.  IGNORE is nonzero if the
05132    value is to be ignored.  */
05133 
05134 static rtx
05135 expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
05136 {
05137   tree id, decl;
05138   tree call;
05139 
05140   /* If we are not profiling, just call the function.  */
05141   if (!profile_arc_flag)
05142     return NULL_RTX;
05143 
05144   /* Otherwise call the wrapper.  This should be equivalent for the rest of
05145      compiler, so the code does not diverge, and the wrapper may run the
05146      code necessary for keeping the profiling sane.  */
05147 
05148   switch (DECL_FUNCTION_CODE (fn))
05149     {
05150     case BUILT_IN_FORK:
05151       id = get_identifier ("__gcov_fork");
05152       break;
05153 
05154     case BUILT_IN_EXECL:
05155       id = get_identifier ("__gcov_execl");
05156       break;
05157 
05158     case BUILT_IN_EXECV:
05159       id = get_identifier ("__gcov_execv");
05160       break;
05161 
05162     case BUILT_IN_EXECLP:
05163       id = get_identifier ("__gcov_execlp");
05164       break;
05165 
05166     case BUILT_IN_EXECLE:
05167       id = get_identifier ("__gcov_execle");
05168       break;
05169 
05170     case BUILT_IN_EXECVP:
05171       id = get_identifier ("__gcov_execvp");
05172       break;
05173 
05174     case BUILT_IN_EXECVE:
05175       id = get_identifier ("__gcov_execve");
05176       break;
05177 
05178     default:
05179       gcc_unreachable ();
05180     }
05181 
05182   decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
05183   DECL_EXTERNAL (decl) = 1;
05184   TREE_PUBLIC (decl) = 1;
05185   DECL_ARTIFICIAL (decl) = 1;
05186   TREE_NOTHROW (decl) = 1;
05187   call = build_function_call_expr (decl, arglist);
05188 
05189   return expand_call (call, target, ignore);
05190 }
05191 
05192 /* Expand an expression EXP that calls a built-in function,
05193    with result going to TARGET if that's convenient
05194    (and in mode MODE if that's convenient).
05195    SUBTARGET may be used as the target for computing one of EXP's operands.
05196    IGNORE is nonzero if the value is to be ignored.  */
05197 
05198 rtx
05199 expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
05200     int ignore)
05201 {
05202   tree fndecl = get_callee_fndecl (exp);
05203   tree arglist = TREE_OPERAND (exp, 1);
05204   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
05205   enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
05206 
05207   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
05208     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
05209 
05210   /* When not optimizing, generate calls to library functions for a certain
05211      set of builtins.  */
05212   if (!optimize
05213       && !CALLED_AS_BUILT_IN (fndecl)
05214       && DECL_ASSEMBLER_NAME_SET_P (fndecl)
05215       && fcode != BUILT_IN_ALLOCA)
05216     return expand_call (exp, target, ignore);
05217 
05218   /* The built-in function expanders test for target == const0_rtx
05219      to determine whether the function's result will be ignored.  */
05220   if (ignore)
05221     target = const0_rtx;
05222 
05223   /* If the result of a pure or const built-in function is ignored, and
05224      none of its arguments are volatile, we can avoid expanding the
05225      built-in call and just evaluate the arguments for side-effects.  */
05226   if (target == const0_rtx
05227       && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
05228     {
05229       bool volatilep = false;
05230       tree arg;
05231 
05232       for (arg = arglist; arg; arg = TREE_CHAIN (arg))
05233   if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
05234     {
05235       volatilep = true;
05236       break;
05237     }
05238 
05239       if (! volatilep)
05240   {
05241     for (arg = arglist; arg; arg = TREE_CHAIN (arg))
05242       expand_expr (TREE_VALUE (arg), const0_rtx,
05243        VOIDmode, EXPAND_NORMAL);
05244     return const0_rtx;
05245   }
05246     }
05247 
05248   switch (fcode)
05249     {
05250     case BUILT_IN_FABS:
05251     case BUILT_IN_FABSF:
05252     case BUILT_IN_FABSL:
05253       target = expand_builtin_fabs (arglist, target, subtarget);
05254       if (target)
05255         return target;
05256       break;
05257 
05258     case BUILT_IN_COPYSIGN:
05259     case BUILT_IN_COPYSIGNF:
05260     case BUILT_IN_COPYSIGNL:
05261       target = expand_builtin_copysign (arglist, target, subtarget);
05262       if (target)
05263   return target;
05264       break;
05265 
05266       /* Just do a normal library call if we were unable to fold
05267    the values.  */
05268     case BUILT_IN_CABS:
05269     case BUILT_IN_CABSF:
05270     case BUILT_IN_CABSL:
05271       break;
05272 
05273     case BUILT_IN_EXP:
05274     case BUILT_IN_EXPF:
05275     case BUILT_IN_EXPL:
05276     case BUILT_IN_EXP10:
05277     case BUILT_IN_EXP10F:
05278     case BUILT_IN_EXP10L:
05279     case BUILT_IN_POW10:
05280     case BUILT_IN_POW10F:
05281     case BUILT_IN_POW10L:
05282     case BUILT_IN_EXP2:
05283     case BUILT_IN_EXP2F:
05284     case BUILT_IN_EXP2L:
05285     case BUILT_IN_EXPM1:
05286     case BUILT_IN_EXPM1F:
05287     case BUILT_IN_EXPM1L:
05288     case BUILT_IN_LOGB:
05289     case BUILT_IN_LOGBF:
05290     case BUILT_IN_LOGBL:
05291     case BUILT_IN_ILOGB:
05292     case BUILT_IN_ILOGBF:
05293     case BUILT_IN_ILOGBL:
05294     case BUILT_IN_LOG:
05295     case BUILT_IN_LOGF:
05296     case BUILT_IN_LOGL:
05297     case BUILT_IN_LOG10:
05298     case BUILT_IN_LOG10F:
05299     case BUILT_IN_LOG10L:
05300     case BUILT_IN_LOG2:
05301     case BUILT_IN_LOG2F:
05302     case BUILT_IN_LOG2L:
05303     case BUILT_IN_LOG1P:
05304     case BUILT_IN_LOG1PF:
05305     case BUILT_IN_LOG1PL:
05306     case BUILT_IN_TAN:
05307     case BUILT_IN_TANF:
05308     case BUILT_IN_TANL:
05309     case BUILT_IN_ASIN:
05310     case BUILT_IN_ASINF:
05311     case BUILT_IN_ASINL:
05312     case BUILT_IN_ACOS:
05313     case BUILT_IN_ACOSF:
05314     case BUILT_IN_ACOSL:
05315     case BUILT_IN_ATAN:
05316     case BUILT_IN_ATANF:
05317     case BUILT_IN_ATANL:
05318       /* Treat these like sqrt only if unsafe math optimizations are allowed,
05319    because of possible accuracy problems.  */
05320       if (! flag_unsafe_math_optimizations)
05321   break;
05322     case BUILT_IN_SQRT:
05323     case BUILT_IN_SQRTF:
05324     case BUILT_IN_SQRTL:
05325     case BUILT_IN_FLOOR:
05326     case BUILT_IN_FLOORF:
05327     case BUILT_IN_FLOORL:
05328     case BUILT_IN_CEIL:
05329     case BUILT_IN_CEILF:
05330     case BUILT_IN_CEILL:
05331     case BUILT_IN_TRUNC:
05332     case BUILT_IN_TRUNCF:
05333     case BUILT_IN_TRUNCL:
05334     case BUILT_IN_ROUND:
05335     case BUILT_IN_ROUNDF:
05336     case BUILT_IN_ROUNDL:
05337     case BUILT_IN_NEARBYINT:
05338     case BUILT_IN_NEARBYINTF:
05339     case BUILT_IN_NEARBYINTL:
05340     case BUILT_IN_RINT:
05341     case BUILT_IN_RINTF:
05342     case BUILT_IN_RINTL:
05343       target = expand_builtin_mathfn (exp, target, subtarget);
05344       if (target)
05345   return target;
05346       break;
05347 
05348     case BUILT_IN_POW:
05349     case BUILT_IN_POWF:
05350     case BUILT_IN_POWL:
05351       target = expand_builtin_pow (exp, target, subtarget);
05352       if (target)
05353   return target;
05354       break;
05355 
05356     case BUILT_IN_POWI:
05357     case BUILT_IN_POWIF:
05358     case BUILT_IN_POWIL:
05359       target = expand_builtin_powi (exp, target, subtarget);
05360       if (target)
05361   return target;
05362       break;
05363 
05364     case BUILT_IN_ATAN2:
05365     case BUILT_IN_ATAN2F:
05366     case BUILT_IN_ATAN2L:
05367     case BUILT_IN_LDEXP:
05368     case BUILT_IN_LDEXPF:
05369     case BUILT_IN_LDEXPL:
05370     case BUILT_IN_FMOD:
05371     case BUILT_IN_FMODF:
05372     case BUILT_IN_FMODL:
05373     case BUILT_IN_DREM:
05374     case BUILT_IN_DREMF:
05375     case BUILT_IN_DREML:
05376       if (! flag_unsafe_math_optimizations)
05377   break;
05378       target = expand_builtin_mathfn_2 (exp, target, subtarget);
05379       if (target)
05380   return target;
05381       break;
05382 
05383     case BUILT_IN_SIN:
05384     case BUILT_IN_SINF:
05385     case BUILT_IN_SINL:
05386     case BUILT_IN_COS:
05387     case BUILT_IN_COSF:
05388     case BUILT_IN_COSL:
05389       if (! flag_unsafe_math_optimizations)
05390   break;
05391       target = expand_builtin_mathfn_3 (exp, target, subtarget);
05392       if (target)
05393   return target;
05394       break;
05395 
05396     case BUILT_IN_APPLY_ARGS:
05397       return expand_builtin_apply_args ();
05398 
05399       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
05400    FUNCTION with a copy of the parameters described by
05401    ARGUMENTS, and ARGSIZE.  It returns a block of memory
05402    allocated on the stack into which is stored all the registers
05403    that might possibly be used for returning the result of a
05404    function.  ARGUMENTS is the value returned by
05405    __builtin_apply_args.  ARGSIZE is the number of bytes of
05406    arguments that must be copied.  ??? How should this value be
05407    computed?  We'll also need a safe worst case value for varargs
05408    functions.  */
05409     case BUILT_IN_APPLY:
05410       if (!validate_arglist (arglist, POINTER_TYPE,
05411            POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
05412     && !validate_arglist (arglist, REFERENCE_TYPE,
05413         POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
05414   return const0_rtx;
05415       else
05416   {
05417     int i;
05418     tree t;
05419     rtx ops[3];
05420 
05421     for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
05422       ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
05423 
05424     return expand_builtin_apply (ops[0], ops[1], ops[2]);
05425   }
05426 
05427       /* __builtin_return (RESULT) causes the function to return the
05428    value described by RESULT.  RESULT is address of the block of
05429    memory returned by __builtin_apply.  */
05430     case BUILT_IN_RETURN:
05431       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
05432   expand_builtin_return (expand_expr (TREE_VALUE (arglist),
05433               NULL_RTX, VOIDmode, 0));
05434       return const0_rtx;
05435 
05436     case BUILT_IN_SAVEREGS:
05437       return expand_builtin_saveregs ();
05438 
05439     case BUILT_IN_ARGS_INFO:
05440       return expand_builtin_args_info (arglist);
05441 
05442       /* Return the address of the first anonymous stack arg.  */
05443     case BUILT_IN_NEXT_ARG:
05444       if (fold_builtin_next_arg (arglist))
05445         return const0_rtx;
05446       return expand_builtin_next_arg ();
05447 
05448     case BUILT_IN_CLASSIFY_TYPE:
05449       return expand_builtin_classify_type (arglist);
05450 
05451     case BUILT_IN_CONSTANT_P:
05452       return const0_rtx;
05453 
05454     case BUILT_IN_FRAME_ADDRESS:
05455     case BUILT_IN_RETURN_ADDRESS:
05456       return expand_builtin_frame_address (fndecl, arglist);
05457 
05458     /* Returns the address of the area where the structure is returned.
05459        0 otherwise.  */
05460     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
05461       if (arglist != 0
05462     || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
05463     || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
05464   return const0_rtx;
05465       else
05466   return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
05467 
05468     case BUILT_IN_ALLOCA:
05469       target = expand_builtin_alloca (arglist, target);
05470       if (target)
05471   return target;
05472       break;
05473 
05474     case BUILT_IN_STACK_SAVE:
05475       return expand_stack_save ();
05476 
05477     case BUILT_IN_STACK_RESTORE:
05478       expand_stack_restore (TREE_VALUE (arglist));
05479       return const0_rtx;
05480 
05481     case BUILT_IN_FFS:
05482     case BUILT_IN_FFSL:
05483     case BUILT_IN_FFSLL:
05484     case BUILT_IN_FFSIMAX:
05485       target = expand_builtin_unop (target_mode, arglist, target,
05486             subtarget, ffs_optab);
05487       if (target)
05488   return target;
05489       break;
05490 
05491     case BUILT_IN_CLZ:
05492     case BUILT_IN_CLZL:
05493     case BUILT_IN_CLZLL:
05494     case BUILT_IN_CLZIMAX:
05495       target = expand_builtin_unop (target_mode, arglist, target,
05496             subtarget, clz_optab);
05497       if (target)
05498   return target;
05499       break;
05500 
05501     case BUILT_IN_CTZ:
05502     case BUILT_IN_CTZL:
05503     case BUILT_IN_CTZLL:
05504     case BUILT_IN_CTZIMAX:
05505       target = expand_builtin_unop (target_mode, arglist, target,
05506             subtarget, ctz_optab);
05507       if (target)
05508   return target;
05509       break;
05510 
05511     case BUILT_IN_POPCOUNT:
05512     case BUILT_IN_POPCOUNTL:
05513     case BUILT_IN_POPCOUNTLL:
05514     case BUILT_IN_POPCOUNTIMAX:
05515       target = expand_builtin_unop (target_mode, arglist, target,
05516             subtarget, popcount_optab);
05517       if (target)
05518   return target;
05519       break;
05520 
05521     case BUILT_IN_PARITY:
05522     case BUILT_IN_PARITYL:
05523     case BUILT_IN_PARITYLL:
05524     case BUILT_IN_PARITYIMAX:
05525       target = expand_builtin_unop (target_mode, arglist, target,
05526             subtarget, parity_optab);
05527       if (target)
05528   return target;
05529       break;
05530 
05531     case BUILT_IN_STRLEN:
05532       target = expand_builtin_strlen (arglist, target, target_mode);
05533       if (target)
05534   return target;
05535       break;
05536 
05537     case BUILT_IN_STRCPY:
05538       target = expand_builtin_strcpy (exp, target, mode);
05539       if (target)
05540   return target;
05541       break;
05542 
05543     case BUILT_IN_STRNCPY:
05544       target = expand_builtin_strncpy (exp, target, mode);
05545       if (target)
05546   return target;
05547       break;
05548 
05549     case BUILT_IN_STPCPY:
05550       target = expand_builtin_stpcpy (exp, target, mode);
05551       if (target)
05552   return target;
05553       break;
05554 
05555     case BUILT_IN_STRCAT:
05556       target = expand_builtin_strcat (arglist, TREE_TYPE (exp), target, mode);
05557       if (target)
05558   return target;
05559       break;
05560 
05561     case BUILT_IN_STRNCAT:
05562       target = expand_builtin_strncat (arglist, target, mode);
05563       if (target)
05564   return target;
05565       break;
05566 
05567     case BUILT_IN_STRSPN:
05568       target = expand_builtin_strspn (arglist, target, mode);
05569       if (target)
05570   return target;
05571       break;
05572 
05573     case BUILT_IN_STRCSPN:
05574       target = expand_builtin_strcspn (arglist, target, mode);
05575       if (target)
05576   return target;
05577       break;
05578 
05579     case BUILT_IN_STRSTR:
05580       target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
05581       if (target)
05582   return target;
05583       break;
05584 
05585     case BUILT_IN_STRPBRK:
05586       target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
05587       if (target)
05588   return target;
05589       break;
05590 
05591     case BUILT_IN_INDEX:
05592     case BUILT_IN_STRCHR:
05593       target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
05594       if (target)
05595   return target;
05596       break;
05597 
05598     case BUILT_IN_RINDEX:
05599     case BUILT_IN_STRRCHR:
05600       target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
05601       if (target)
05602   return target;
05603       break;
05604 
05605     case BUILT_IN_MEMCPY:
05606       target = expand_builtin_memcpy (exp, target, mode);
05607       if (target)
05608   return target;
05609       break;
05610 
05611     case BUILT_IN_MEMPCPY:
05612       target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
05613       if (target)
05614   return target;
05615       break;
05616 
05617     case BUILT_IN_MEMMOVE:
05618       target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
05619                mode, exp);
05620       if (target)
05621   return target;
05622       break;
05623 
05624     case BUILT_IN_BCOPY:
05625       target = expand_builtin_bcopy (exp);
05626       if (target)
05627   return target;
05628       break;
05629 
05630     case BUILT_IN_MEMSET:
05631       target = expand_builtin_memset (arglist, target, mode, exp);
05632       if (target)
05633   return target;
05634       break;
05635 
05636     case BUILT_IN_BZERO:
05637       target = expand_builtin_bzero (exp);
05638       if (target)
05639   return target;
05640       break;
05641 
05642     case BUILT_IN_STRCMP:
05643       target = expand_builtin_strcmp (exp, target, mode);
05644       if (target)
05645   return target;
05646       break;
05647 
05648     case BUILT_IN_STRNCMP:
05649       target = expand_builtin_strncmp (exp, target, mode);
05650       if (target)
05651   return target;
05652       break;
05653 
05654     case BUILT_IN_BCMP:
05655     case BUILT_IN_MEMCMP:
05656       target = expand_builtin_memcmp (exp, arglist, target, mode);
05657       if (target)
05658   return target;
05659       break;
05660 
05661     case BUILT_IN_SETJMP:
05662       target = expand_builtin_setjmp (arglist, target);
05663       if (target)
05664   return target;
05665       break;
05666 
05667       /* __builtin_longjmp is passed a pointer to an array of five words.
05668    It's similar to the C library longjmp function but works with
05669    __builtin_setjmp above.  */
05670     case BUILT_IN_LONGJMP:
05671       if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
05672   break;
05673       else
05674   {
05675     rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
05676               VOIDmode, 0);
05677     rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
05678            NULL_RTX, VOIDmode, 0);
05679 
05680     if (value != const1_rtx)
05681       {
05682         error ("%<__builtin_longjmp%> second argument must be 1");
05683         return const0_rtx;
05684       }
05685 
05686     expand_builtin_longjmp (buf_addr, value);
05687     return const0_rtx;
05688   }
05689 
05690     case BUILT_IN_NONLOCAL_GOTO:
05691       target = expand_builtin_nonlocal_goto (arglist);
05692       if (target)
05693   return target;
05694       break;
05695 
05696       /* This updates the setjmp buffer that is its argument with the value
05697    of the current stack pointer.  */
05698     case BUILT_IN_UPDATE_SETJMP_BUF:
05699       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
05700   {
05701     rtx buf_addr
05702       = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
05703 
05704     expand_builtin_update_setjmp_buf (buf_addr);
05705     return const0_rtx;
05706   }
05707       break;
05708 
05709     case BUILT_IN_TRAP:
05710       expand_builtin_trap ();
05711       return const0_rtx;
05712 
05713     case BUILT_IN_PRINTF:
05714       target = expand_builtin_printf (exp, target, mode, false);
05715       if (target)
05716   return target;
05717       break;
05718 
05719     case BUILT_IN_PRINTF_UNLOCKED:
05720       target = expand_builtin_printf (exp, target, mode, true);
05721       if (target)
05722   return target;
05723       break;
05724 
05725     case BUILT_IN_FPUTS:
05726       target = expand_builtin_fputs (arglist, target, false);
05727       if (target)
05728   return target;
05729       break;
05730     case BUILT_IN_FPUTS_UNLOCKED:
05731       target = expand_builtin_fputs (arglist, target, true);
05732       if (target)
05733   return target;
05734       break;
05735 
05736     case BUILT_IN_FPRINTF:
05737       target = expand_builtin_fprintf (exp, target, mode, false);
05738       if (target)
05739   return target;
05740       break;
05741 
05742     case BUILT_IN_FPRINTF_UNLOCKED:
05743       target = expand_builtin_fprintf (exp, target, mode, true);
05744       if (target)
05745   return target;
05746       break;
05747 
05748     case BUILT_IN_SPRINTF:
05749       target = expand_builtin_sprintf (arglist, target, mode);
05750       if (target)
05751   return target;
05752       break;
05753 
05754     case BUILT_IN_SIGNBIT:
05755     case BUILT_IN_SIGNBITF:
05756     case BUILT_IN_SIGNBITL:
05757       target = expand_builtin_signbit (exp, target);
05758       if (target)
05759   return target;
05760       break;
05761 
05762       /* Various hooks for the DWARF 2 __throw routine.  */
05763     case BUILT_IN_UNWIND_INIT:
05764       expand_builtin_unwind_init ();
05765       return const0_rtx;
05766     case BUILT_IN_DWARF_CFA:
05767       return virtual_cfa_rtx;
05768 #ifdef DWARF2_UNWIND_INFO
05769     case BUILT_IN_DWARF_SP_COLUMN:
05770       return expand_builtin_dwarf_sp_column ();
05771     case BUILT_IN_INIT_DWARF_REG_SIZES:
05772       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
05773       return const0_rtx;
05774 #endif
05775     case BUILT_IN_FROB_RETURN_ADDR:
05776       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
05777     case BUILT_IN_EXTRACT_RETURN_ADDR:
05778       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
05779     case BUILT_IN_EH_RETURN:
05780       expand_builtin_eh_return (TREE_VALUE (arglist),
05781         TREE_VALUE (TREE_CHAIN (arglist)));
05782       return const0_rtx;
05783 #ifdef EH_RETURN_DATA_REGNO
05784     case BUILT_IN_EH_RETURN_DATA_REGNO:
05785       return expand_builtin_eh_return_data_regno (arglist);
05786 #endif
05787     case BUILT_IN_EXTEND_POINTER:
05788       return expand_builtin_extend_pointer (TREE_VALUE (arglist));
05789 
05790     case BUILT_IN_VA_START:
05791     case BUILT_IN_STDARG_START:
05792       return expand_builtin_va_start (arglist);
05793     case BUILT_IN_VA_END:
05794       return expand_builtin_va_end (arglist);
05795     case BUILT_IN_VA_COPY:
05796       return expand_builtin_va_copy (arglist);
05797     case BUILT_IN_EXPECT:
05798       return expand_builtin_expect (arglist, target);
05799     case BUILT_IN_PREFETCH:
05800       expand_builtin_prefetch (arglist);
05801       return const0_rtx;
05802 
05803     case BUILT_IN_PROFILE_FUNC_ENTER:
05804       return expand_builtin_profile_func (false);
05805     case BUILT_IN_PROFILE_FUNC_EXIT:
05806       return expand_builtin_profile_func (true);
05807 
05808     case BUILT_IN_INIT_TRAMPOLINE:
05809       return expand_builtin_init_trampoline (arglist);
05810     case BUILT_IN_ADJUST_TRAMPOLINE:
05811       return expand_builtin_adjust_trampoline (arglist);
05812 
05813     case BUILT_IN_FORK:
05814     case BUILT_IN_EXECL:
05815     case BUILT_IN_EXECV:
05816     case BUILT_IN_EXECLP:
05817     case BUILT_IN_EXECLE:
05818     case BUILT_IN_EXECVP:
05819     case BUILT_IN_EXECVE:
05820       target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
05821       if (target)
05822   return target;
05823       break;
05824 
05825     default:  /* just do library call, if unknown builtin */
05826       break;
05827     }
05828 
05829   /* The switch statement above can drop through to cause the function
05830      to be called normally.  */
05831   return expand_call (exp, target, ignore);
05832 }
05833 
05834 /* Determine whether a tree node represents a call to a built-in
05835    function.  If the tree T is a call to a built-in function with
05836    the right number of arguments of the appropriate types, return
05837    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
05838    Otherwise the return value is END_BUILTINS.  */
05839 
05840 enum built_in_function
05841 builtin_mathfn_code (tree t)
05842 {
05843   tree fndecl, arglist, parmlist;
05844   tree argtype, parmtype;
05845 
05846   if (TREE_CODE (t) != CALL_EXPR
05847       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
05848     return END_BUILTINS;
05849 
05850   fndecl = get_callee_fndecl (t);
05851   if (fndecl == NULL_TREE
05852       || TREE_CODE (fndecl) != FUNCTION_DECL
05853       || ! DECL_BUILT_IN (fndecl)
05854       || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
05855     return END_BUILTINS;
05856 
05857   arglist = TREE_OPERAND (t, 1);
05858   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
05859   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
05860     {
05861       /* If a function doesn't take a variable number of arguments,
05862    the last element in the list will have type `void'.  */
05863       parmtype = TREE_VALUE (parmlist);
05864       if (VOID_TYPE_P (parmtype))
05865   {
05866     if (arglist)
05867       return END_BUILTINS;
05868     return DECL_FUNCTION_CODE (fndecl);
05869   }
05870 
05871       if (! arglist)
05872   return END_BUILTINS;
05873 
05874       argtype = TREE_TYPE (TREE_VALUE (arglist));
05875 
05876       if (SCALAR_FLOAT_TYPE_P (parmtype))
05877   {
05878     if (! SCALAR_FLOAT_TYPE_P (argtype))
05879       return END_BUILTINS;
05880   }
05881       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
05882   {
05883     if (! COMPLEX_FLOAT_TYPE_P (argtype))
05884       return END_BUILTINS;
05885   }
05886       else if (POINTER_TYPE_P (parmtype))
05887   {
05888     if (! POINTER_TYPE_P (argtype))
05889       return END_BUILTINS;
05890   }
05891       else if (INTEGRAL_TYPE_P (parmtype))
05892   {
05893     if (! INTEGRAL_TYPE_P (argtype))
05894       return END_BUILTINS;
05895   }
05896       else
05897   return END_BUILTINS;
05898 
05899       arglist = TREE_CHAIN (arglist);
05900     }
05901 
05902   /* Variable-length argument list.  */
05903   return DECL_FUNCTION_CODE (fndecl);
05904 }
05905 
05906 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
05907    constant.  ARGLIST is the argument list of the call.  */
05908 
05909 static tree
05910 fold_builtin_constant_p (tree arglist)
05911 {
05912   if (arglist == 0)
05913     return 0;
05914 
05915   arglist = TREE_VALUE (arglist);
05916 
05917   /* We return 1 for a numeric type that's known to be a constant
05918      value at compile-time or for an aggregate type that's a
05919      literal constant.  */
05920   STRIP_NOPS (arglist);
05921 
05922   /* If we know this is a constant, emit the constant of one.  */
05923   if (CONSTANT_CLASS_P (arglist)
05924       || (TREE_CODE (arglist) == CONSTRUCTOR
05925     && TREE_CONSTANT (arglist)))
05926     return integer_one_node;
05927   if (TREE_CODE (arglist) == ADDR_EXPR)
05928     {
05929        tree op = TREE_OPERAND (arglist, 0);
05930        if (TREE_CODE (op) == STRING_CST
05931      || (TREE_CODE (op) == ARRAY_REF
05932          && integer_zerop (TREE_OPERAND (op, 1))
05933          && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
05934    return integer_one_node;
05935     }
05936 
05937   /* If this expression has side effects, show we don't know it to be a
05938      constant.  Likewise if it's a pointer or aggregate type since in
05939      those case we only want literals, since those are only optimized
05940      when generating RTL, not later.
05941      And finally, if we are compiling an initializer, not code, we
05942      need to return a definite result now; there's not going to be any
05943      more optimization done.  */
05944   if (TREE_SIDE_EFFECTS (arglist)
05945       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
05946       || POINTER_TYPE_P (TREE_TYPE (arglist))
05947       || cfun == 0)
05948     return integer_zero_node;
05949 
05950   return 0;
05951 }
05952 
05953 /* Fold a call to __builtin_expect, if we expect that a comparison against
05954    the argument will fold to a constant.  In practice, this means a true
05955    constant or the address of a non-weak symbol.  ARGLIST is the argument
05956    list of the call.  */
05957 
05958 static tree
05959 fold_builtin_expect (tree arglist)
05960 {
05961   tree arg, inner;
05962 
05963   if (arglist == 0)
05964     return 0;
05965 
05966   arg = TREE_VALUE (arglist);
05967 
05968   /* If the argument isn't invariant, then there's nothing we can do.  */
05969   if (!TREE_INVARIANT (arg))
05970     return 0;
05971 
05972   /* If we're looking at an address of a weak decl, then do not fold.  */
05973   inner = arg;
05974   STRIP_NOPS (inner);
05975   if (TREE_CODE (inner) == ADDR_EXPR)
05976     {
05977       do
05978   {
05979     inner = TREE_OPERAND (inner, 0);
05980   }
05981       while (TREE_CODE (inner) == COMPONENT_REF
05982        || TREE_CODE (inner) == ARRAY_REF);
05983       if (DECL_P (inner) && DECL_WEAK (inner))
05984   return 0;
05985     }
05986 
05987   /* Otherwise, ARG already has the proper type for the return value.  */
05988   return arg;
05989 }
05990 
05991 /* Fold a call to __builtin_classify_type.  */
05992 
05993 static tree
05994 fold_builtin_classify_type (tree arglist)
05995 {
05996   if (arglist == 0)
05997     return build_int_cst (NULL_TREE, no_type_class);
05998 
05999   return build_int_cst (NULL_TREE,
06000       type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
06001 }
06002 
06003 /* Fold a call to __builtin_strlen.  */
06004 
06005 static tree
06006 fold_builtin_strlen (tree arglist)
06007 {
06008   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
06009     return NULL_TREE;
06010   else
06011     {
06012       tree len = c_strlen (TREE_VALUE (arglist), 0);
06013 
06014       if (len)
06015   {
06016     /* Convert from the internal "sizetype" type to "size_t".  */
06017     if (size_type_node)
06018       len = fold_convert (size_type_node, len);
06019     return len;
06020   }
06021 
06022       return NULL_TREE;
06023     }
06024 }
06025 
06026 /* Fold a call to __builtin_inf or __builtin_huge_val.  */
06027 
06028 static tree
06029 fold_builtin_inf (tree type, int warn)
06030 {
06031   REAL_VALUE_TYPE real;
06032 
06033   /* __builtin_inff is intended to be usable to define INFINITY on all
06034      targets.  If an infinity is not available, INFINITY expands "to a
06035      positive constant of type float that overflows at translation
06036      time", footnote "In this case, using INFINITY will violate the
06037      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
06038      Thus we pedwarn to ensure this constraint violation is
06039      diagnosed.  */
06040   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
06041     pedwarn ("target format does not support infinity");
06042 
06043   real_inf (&real);
06044   return build_real (type, real);
06045 }
06046 
06047 /* Fold a call to __builtin_nan or __builtin_nans.  */
06048 
06049 static tree
06050 fold_builtin_nan (tree arglist, tree type, int quiet)
06051 {
06052   REAL_VALUE_TYPE real;
06053   const char *str;
06054 
06055   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
06056     return 0;
06057   str = c_getstr (TREE_VALUE (arglist));
06058   if (!str)
06059     return 0;
06060 
06061   if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
06062     return 0;
06063 
06064   return build_real (type, real);
06065 }
06066 
06067 /* Return true if the floating point expression T has an integer value.
06068    We also allow +Inf, -Inf and NaN to be considered integer values.  */
06069 
06070 static bool
06071 integer_valued_real_p (tree t)
06072 {
06073   switch (TREE_CODE (t))
06074     {
06075     case FLOAT_EXPR:
06076       return true;
06077 
06078     case ABS_EXPR:
06079     case SAVE_EXPR:
06080     case NON_LVALUE_EXPR:
06081       return integer_valued_real_p (TREE_OPERAND (t, 0));
06082 
06083     case COMPOUND_EXPR:
06084     case MODIFY_EXPR:
06085     case BIND_EXPR:
06086       return integer_valued_real_p (TREE_OPERAND (t, 1));
06087 
06088     case PLUS_EXPR:
06089     case MINUS_EXPR:
06090     case MULT_EXPR:
06091     case MIN_EXPR:
06092     case MAX_EXPR:
06093       return integer_valued_real_p (TREE_OPERAND (t, 0))
06094        && integer_valued_real_p (TREE_OPERAND (t, 1));
06095 
06096     case COND_EXPR:
06097       return integer_valued_real_p (TREE_OPERAND (t, 1))
06098        && integer_valued_real_p (TREE_OPERAND (t, 2));
06099 
06100     case REAL_CST:
06101       if (! TREE_CONSTANT_OVERFLOW (t))
06102       {
06103         REAL_VALUE_TYPE c, cint;
06104 
06105   c = TREE_REAL_CST (t);
06106   real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
06107   return real_identical (&c, &cint);
06108       }
06109 
06110     case NOP_EXPR:
06111       {
06112   tree type = TREE_TYPE (TREE_OPERAND (t, 0));
06113   if (TREE_CODE (type) == INTEGER_TYPE)
06114     return true;
06115   if (TREE_CODE (type) == REAL_TYPE)
06116     return integer_valued_real_p (TREE_OPERAND (t, 0));
06117   break;
06118       }
06119 
06120     case CALL_EXPR:
06121       switch (builtin_mathfn_code (t))
06122   {
06123   case BUILT_IN_CEIL:
06124   case BUILT_IN_CEILF:
06125   case BUILT_IN_CEILL:
06126   case BUILT_IN_FLOOR:
06127   case BUILT_IN_FLOORF:
06128   case BUILT_IN_FLOORL:
06129   case BUILT_IN_NEARBYINT:
06130   case BUILT_IN_NEARBYINTF:
06131   case BUILT_IN_NEARBYINTL:
06132   case BUILT_IN_RINT:
06133   case BUILT_IN_RINTF:
06134   case BUILT_IN_RINTL:
06135   case BUILT_IN_ROUND:
06136   case BUILT_IN_ROUNDF:
06137   case BUILT_IN_ROUNDL:
06138   case BUILT_IN_TRUNC:
06139   case BUILT_IN_TRUNCF:
06140   case BUILT_IN_TRUNCL:
06141     return true;
06142 
06143   default:
06144     break;
06145   }
06146       break;
06147 
06148     default:
06149       break;
06150     }
06151   return false;
06152 }
06153 
06154 /* EXP is assumed to be builtin call where truncation can be propagated
06155    across (for instance floor((double)f) == (double)floorf (f).
06156    Do the transformation.  */
06157 
06158 static tree
06159 fold_trunc_transparent_mathfn (tree exp)
06160 {
06161   tree fndecl = get_callee_fndecl (exp);
06162   tree arglist = TREE_OPERAND (exp, 1);
06163   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
06164   tree arg;
06165 
06166   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06167     return 0;
06168 
06169   arg = TREE_VALUE (arglist);
06170   /* Integer rounding functions are idempotent.  */
06171   if (fcode == builtin_mathfn_code (arg))
06172     return arg;
06173 
06174   /* If argument is already integer valued, and we don't need to worry
06175      about setting errno, there's no need to perform rounding.  */
06176   if (! flag_errno_math && integer_valued_real_p (arg))
06177     return arg;
06178 
06179   if (optimize)
06180     {
06181       tree arg0 = strip_float_extensions (arg);
06182       tree ftype = TREE_TYPE (exp);
06183       tree newtype = TREE_TYPE (arg0);
06184       tree decl;
06185 
06186       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
06187     && (decl = mathfn_built_in (newtype, fcode)))
06188   {
06189     arglist =
06190       build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
06191     return fold_convert (ftype,
06192              build_function_call_expr (decl, arglist));
06193   }
06194     }
06195   return 0;
06196 }
06197 
06198 /* EXP is assumed to be builtin call which can narrow the FP type of
06199    the argument, for instance lround((double)f) -> lroundf (f).  */
06200 
06201 static tree
06202 fold_fixed_mathfn (tree exp)
06203 {
06204   tree fndecl = get_callee_fndecl (exp);
06205   tree arglist = TREE_OPERAND (exp, 1);
06206   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
06207   tree arg;
06208 
06209   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06210     return 0;
06211 
06212   arg = TREE_VALUE (arglist);
06213 
06214   /* If argument is already integer valued, and we don't need to worry
06215      about setting errno, there's no need to perform rounding.  */
06216   if (! flag_errno_math && integer_valued_real_p (arg))
06217     return fold (build1 (FIX_TRUNC_EXPR, TREE_TYPE (exp), arg));
06218 
06219   if (optimize)
06220     {
06221       tree ftype = TREE_TYPE (arg);
06222       tree arg0 = strip_float_extensions (arg);
06223       tree newtype = TREE_TYPE (arg0);
06224       tree decl;
06225 
06226       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
06227     && (decl = mathfn_built_in (newtype, fcode)))
06228   {
06229     arglist =
06230       build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
06231     return build_function_call_expr (decl, arglist);
06232   }
06233     }
06234   return 0;
06235 }
06236 
06237 /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
06238    is the argument list and TYPE is the return type.  Return
06239    NULL_TREE if no if no simplification can be made.  */
06240 
06241 static tree
06242 fold_builtin_cabs (tree arglist, tree type)
06243 {
06244   tree arg;
06245 
06246   if (!arglist || TREE_CHAIN (arglist))
06247     return NULL_TREE;
06248 
06249   arg = TREE_VALUE (arglist);
06250   if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
06251       || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
06252     return NULL_TREE;
06253 
06254   /* Evaluate cabs of a constant at compile-time.  */
06255   if (flag_unsafe_math_optimizations
06256       && TREE_CODE (arg) == COMPLEX_CST
06257       && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
06258       && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
06259       && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
06260       && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
06261     {
06262       REAL_VALUE_TYPE r, i;
06263 
06264       r = TREE_REAL_CST (TREE_REALPART (arg));
06265       i = TREE_REAL_CST (TREE_IMAGPART (arg));
06266 
06267       real_arithmetic (&r, MULT_EXPR, &r, &r);
06268       real_arithmetic (&i, MULT_EXPR, &i, &i);
06269       real_arithmetic (&r, PLUS_EXPR, &r, &i);
06270       if (real_sqrt (&r, TYPE_MODE (type), &r)
06271     || ! flag_trapping_math)
06272   return build_real (type, r);
06273     }
06274 
06275   /* If either part is zero, cabs is fabs of the other.  */
06276   if (TREE_CODE (arg) == COMPLEX_EXPR
06277       && real_zerop (TREE_OPERAND (arg, 0)))
06278     return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)));
06279   if (TREE_CODE (arg) == COMPLEX_EXPR
06280       && real_zerop (TREE_OPERAND (arg, 1)))
06281     return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)));
06282 
06283   /* Don't do this when optimizing for size.  */
06284   if (flag_unsafe_math_optimizations
06285       && optimize && !optimize_size)
06286     {
06287       tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
06288 
06289       if (sqrtfn != NULL_TREE)
06290   {
06291     tree rpart, ipart, result, arglist;
06292 
06293     arg = builtin_save_expr (arg);
06294 
06295     rpart = fold (build1 (REALPART_EXPR, type, arg));
06296     ipart = fold (build1 (IMAGPART_EXPR, type, arg));
06297 
06298     rpart = builtin_save_expr (rpart);
06299     ipart = builtin_save_expr (ipart);
06300 
06301     result = fold (build2 (PLUS_EXPR, type,
06302          fold (build2 (MULT_EXPR, type,
06303                  rpart, rpart)),
06304          fold (build2 (MULT_EXPR, type,
06305                  ipart, ipart))));
06306 
06307     arglist = build_tree_list (NULL_TREE, result);
06308     return build_function_call_expr (sqrtfn, arglist);
06309   }
06310     }
06311 
06312   return NULL_TREE;
06313 }
06314 
06315 /* Fold a builtin function call to sqrt, sqrtf, or sqrtl.  Return
06316    NULL_TREE if no simplification can be made.  */
06317 
06318 static tree
06319 fold_builtin_sqrt (tree arglist, tree type)
06320 {
06321 
06322   enum built_in_function fcode;
06323   tree arg = TREE_VALUE (arglist);
06324 
06325   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06326     return NULL_TREE;
06327 
06328   /* Optimize sqrt of constant value.  */
06329   if (TREE_CODE (arg) == REAL_CST
06330       && ! TREE_CONSTANT_OVERFLOW (arg))
06331     {
06332       REAL_VALUE_TYPE r, x;
06333 
06334       x = TREE_REAL_CST (arg);
06335       if (real_sqrt (&r, TYPE_MODE (type), &x)
06336     || (!flag_trapping_math && !flag_errno_math))
06337   return build_real (type, r);
06338     }
06339 
06340   /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
06341   fcode = builtin_mathfn_code (arg);
06342   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
06343     {
06344       tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
06345       arg = fold (build2 (MULT_EXPR, type,
06346         TREE_VALUE (TREE_OPERAND (arg, 1)),
06347         build_real (type, dconsthalf)));
06348       arglist = build_tree_list (NULL_TREE, arg);
06349       return build_function_call_expr (expfn, arglist);
06350     }
06351 
06352   /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)).  */
06353   if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
06354     {
06355       tree powfn = mathfn_built_in (type, BUILT_IN_POW);
06356 
06357       if (powfn)
06358   {
06359     tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
06360     tree tree_root;
06361     /* The inner root was either sqrt or cbrt.  */
06362     REAL_VALUE_TYPE dconstroot =
06363       BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
06364 
06365     /* Adjust for the outer root.  */
06366     SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
06367     dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
06368     tree_root = build_real (type, dconstroot);
06369     arglist = tree_cons (NULL_TREE, arg0,
06370              build_tree_list (NULL_TREE, tree_root));
06371     return build_function_call_expr (powfn, arglist);
06372   }
06373     }
06374 
06375   /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5).  */
06376   if (flag_unsafe_math_optimizations
06377       && (fcode == BUILT_IN_POW
06378     || fcode == BUILT_IN_POWF
06379     || fcode == BUILT_IN_POWL))
06380     {
06381       tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
06382       tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
06383       tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
06384       tree narg1;
06385       if (!tree_expr_nonnegative_p (arg0))
06386   arg0 = build1 (ABS_EXPR, type, arg0);
06387       narg1 = fold (build2 (MULT_EXPR, type, arg1,
06388           build_real (type, dconsthalf)));
06389       arglist = tree_cons (NULL_TREE, arg0,
06390          build_tree_list (NULL_TREE, narg1));
06391       return build_function_call_expr (powfn, arglist);
06392     }
06393 
06394   return NULL_TREE;
06395 }
06396 
06397 /* Fold a builtin function call to cbrt, cbrtf, or cbrtl.  Return
06398    NULL_TREE if no simplification can be made.  */
06399 static tree
06400 fold_builtin_cbrt (tree arglist, tree type)
06401 {
06402   tree arg = TREE_VALUE (arglist);
06403   const enum built_in_function fcode = builtin_mathfn_code (arg);
06404 
06405   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06406     return NULL_TREE;
06407 
06408   /* Optimize cbrt of constant value.  */
06409   if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
06410     return arg;
06411 
06412   /* Optimize cbrt(expN(x)) -> expN(x/3).  */
06413   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
06414     {
06415       tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
06416       const REAL_VALUE_TYPE third_trunc =
06417   real_value_truncate (TYPE_MODE (type), dconstthird);
06418       arg = fold (build2 (MULT_EXPR, type,
06419         TREE_VALUE (TREE_OPERAND (arg, 1)),
06420         build_real (type, third_trunc)));
06421       arglist = build_tree_list (NULL_TREE, arg);
06422       return build_function_call_expr (expfn, arglist);
06423     }
06424 
06425   /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
06426   /* We don't optimize cbrt(cbrt(x)) -> pow(x,1/9) because if
06427      x is negative pow will error but cbrt won't.  */
06428   if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode))
06429     {
06430       tree powfn = mathfn_built_in (type, BUILT_IN_POW);
06431 
06432       if (powfn)
06433   {
06434     tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
06435     tree tree_root;
06436     REAL_VALUE_TYPE dconstroot = dconstthird;
06437 
06438     SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
06439     dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
06440     tree_root = build_real (type, dconstroot);
06441     arglist = tree_cons (NULL_TREE, arg0,
06442              build_tree_list (NULL_TREE, tree_root));
06443     return build_function_call_expr (powfn, arglist);
06444   }
06445 
06446     }
06447   return NULL_TREE;
06448 }
06449 
06450 /* Fold function call to builtin sin, sinf, or sinl.  Return
06451    NULL_TREE if no simplification can be made.  */
06452 static tree
06453 fold_builtin_sin (tree arglist)
06454 {
06455   tree arg = TREE_VALUE (arglist);
06456 
06457   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06458     return NULL_TREE;
06459 
06460   /* Optimize sin (0.0) = 0.0.  */
06461   if (real_zerop (arg))
06462     return arg;
06463 
06464   return NULL_TREE;
06465 }
06466 
06467 /* Fold function call to builtin cos, cosf, or cosl.  Return
06468    NULL_TREE if no simplification can be made.  */
06469 static tree
06470 fold_builtin_cos (tree arglist, tree type, tree fndecl)
06471 {
06472   tree arg = TREE_VALUE (arglist);
06473 
06474   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06475     return NULL_TREE;
06476 
06477   /* Optimize cos (0.0) = 1.0.  */
06478   if (real_zerop (arg))
06479     return build_real (type, dconst1);
06480 
06481   /* Optimize cos(-x) into cos (x).  */
06482   if (TREE_CODE (arg) == NEGATE_EXPR)
06483     {
06484       tree args = build_tree_list (NULL_TREE,
06485            TREE_OPERAND (arg, 0));
06486       return build_function_call_expr (fndecl, args);
06487     }
06488 
06489   return NULL_TREE;
06490 }
06491 
06492 /* Fold function call to builtin tan, tanf, or tanl.  Return
06493    NULL_TREE if no simplification can be made.  */
06494 static tree
06495 fold_builtin_tan (tree arglist)
06496 {
06497   enum built_in_function fcode;
06498   tree arg = TREE_VALUE (arglist);
06499 
06500   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06501     return NULL_TREE;
06502 
06503   /* Optimize tan(0.0) = 0.0.  */
06504   if (real_zerop (arg))
06505     return arg;
06506 
06507   /* Optimize tan(atan(x)) = x.  */
06508   fcode = builtin_mathfn_code (arg);
06509   if (flag_unsafe_math_optimizations
06510       && (fcode == BUILT_IN_ATAN
06511     || fcode == BUILT_IN_ATANF
06512     || fcode == BUILT_IN_ATANL))
06513     return TREE_VALUE (TREE_OPERAND (arg, 1));
06514 
06515   return NULL_TREE;
06516 }
06517 
06518 /* Fold function call to builtin atan, atanf, or atanl.  Return
06519    NULL_TREE if no simplification can be made.  */
06520 
06521 static tree
06522 fold_builtin_atan (tree arglist, tree type)
06523 {
06524 
06525   tree arg = TREE_VALUE (arglist);
06526 
06527   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06528     return NULL_TREE;
06529 
06530   /* Optimize atan(0.0) = 0.0.  */
06531   if (real_zerop (arg))
06532     return arg;
06533 
06534   /* Optimize atan(1.0) = pi/4.  */
06535   if (real_onep (arg))
06536     {
06537       REAL_VALUE_TYPE cst;
06538 
06539       real_convert (&cst, TYPE_MODE (type), &dconstpi);
06540       SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
06541       return build_real (type, cst);
06542     }
06543 
06544   return NULL_TREE;
06545 }
06546 
06547 /* Fold function call to builtin trunc, truncf or truncl.  Return
06548    NULL_TREE if no simplification can be made.  */
06549 
06550 static tree
06551 fold_builtin_trunc (tree exp)
06552 {
06553   tree arglist = TREE_OPERAND (exp, 1);
06554   tree arg;
06555 
06556   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06557     return 0;
06558 
06559   /* Optimize trunc of constant value.  */
06560   arg = TREE_VALUE (arglist);
06561   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
06562     {
06563       REAL_VALUE_TYPE r, x;
06564       tree type = TREE_TYPE (exp);
06565 
06566       x = TREE_REAL_CST (arg);
06567       real_trunc (&r, TYPE_MODE (type), &x);
06568       return build_real (type, r);
06569     }
06570 
06571   return fold_trunc_transparent_mathfn (exp);
06572 }
06573 
06574 /* Fold function call to builtin floor, floorf or floorl.  Return
06575    NULL_TREE if no simplification can be made.  */
06576 
06577 static tree
06578 fold_builtin_floor (tree exp)
06579 {
06580   tree arglist = TREE_OPERAND (exp, 1);
06581   tree arg;
06582 
06583   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06584     return 0;
06585 
06586   /* Optimize floor of constant value.  */
06587   arg = TREE_VALUE (arglist);
06588   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
06589     {
06590       REAL_VALUE_TYPE x;
06591 
06592       x = TREE_REAL_CST (arg);
06593       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
06594   {
06595     tree type = TREE_TYPE (exp);
06596     REAL_VALUE_TYPE r;
06597 
06598     real_floor (&r, TYPE_MODE (type), &x);
06599     return build_real (type, r);
06600   }
06601     }
06602 
06603   return fold_trunc_transparent_mathfn (exp);
06604 }
06605 
06606 /* Fold function call to builtin ceil, ceilf or ceill.  Return
06607    NULL_TREE if no simplification can be made.  */
06608 
06609 static tree
06610 fold_builtin_ceil (tree exp)
06611 {
06612   tree arglist = TREE_OPERAND (exp, 1);
06613   tree arg;
06614 
06615   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06616     return 0;
06617 
06618   /* Optimize ceil of constant value.  */
06619   arg = TREE_VALUE (arglist);
06620   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
06621     {
06622       REAL_VALUE_TYPE x;
06623 
06624       x = TREE_REAL_CST (arg);
06625       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
06626   {
06627     tree type = TREE_TYPE (exp);
06628     REAL_VALUE_TYPE r;
06629 
06630     real_ceil (&r, TYPE_MODE (type), &x);
06631     return build_real (type, r);
06632   }
06633     }
06634 
06635   return fold_trunc_transparent_mathfn (exp);
06636 }
06637 
06638 /* Fold function call to builtin round, roundf or roundl.  Return
06639    NULL_TREE if no simplification can be made.  */
06640 
06641 static tree
06642 fold_builtin_round (tree exp)
06643 {
06644   tree arglist = TREE_OPERAND (exp, 1);
06645   tree arg;
06646 
06647   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06648     return 0;
06649 
06650   /* Optimize round of constant value.  */
06651   arg = TREE_VALUE (arglist);
06652   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
06653     {
06654       REAL_VALUE_TYPE x;
06655 
06656       x = TREE_REAL_CST (arg);
06657       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
06658   {
06659     tree type = TREE_TYPE (exp);
06660     REAL_VALUE_TYPE r;
06661 
06662     real_round (&r, TYPE_MODE (type), &x);
06663     return build_real (type, r);
06664   }
06665     }
06666 
06667   return fold_trunc_transparent_mathfn (exp);
06668 }
06669 
06670 /* Fold function call to builtin lround, lroundf or lroundl (or the
06671    corresponding long long versions).  Return NULL_TREE if no
06672    simplification can be made.  */
06673 
06674 static tree
06675 fold_builtin_lround (tree exp)
06676 {
06677   tree arglist = TREE_OPERAND (exp, 1);
06678   tree arg;
06679 
06680   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06681     return 0;
06682 
06683   /* Optimize lround of constant value.  */
06684   arg = TREE_VALUE (arglist);
06685   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
06686     {
06687       const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
06688 
06689       if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
06690   {
06691     tree itype = TREE_TYPE (exp), ftype = TREE_TYPE (arg), result;
06692     HOST_WIDE_INT hi, lo;
06693     REAL_VALUE_TYPE r;
06694 
06695     real_round (&r, TYPE_MODE (ftype), &x);
06696     REAL_VALUE_TO_INT (&lo, &hi, r);
06697     result = build_int_cst_wide (NULL_TREE, lo, hi);
06698     if (int_fits_type_p (result, itype))
06699       return fold_convert (itype, result);
06700   }
06701     }
06702 
06703   return fold_fixed_mathfn (exp);
06704 }
06705 
06706 /* Fold function call to builtin ffs, clz, ctz, popcount and parity
06707    and their long and long long variants (i.e. ffsl and ffsll).
06708    Return NULL_TREE if no simplification can be made.  */
06709 
06710 static tree
06711 fold_builtin_bitop (tree exp)
06712 {
06713   tree fndecl = get_callee_fndecl (exp);
06714   tree arglist = TREE_OPERAND (exp, 1);
06715   tree arg;
06716 
06717   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
06718     return NULL_TREE;
06719 
06720   /* Optimize for constant argument.  */
06721   arg = TREE_VALUE (arglist);
06722   if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
06723     {
06724       HOST_WIDE_INT hi, width, result;
06725       unsigned HOST_WIDE_INT lo;
06726       tree type;
06727 
06728       type = TREE_TYPE (arg);
06729       width = TYPE_PRECISION (type);
06730       lo = TREE_INT_CST_LOW (arg);
06731 
06732       /* Clear all the bits that are beyond the type's precision.  */
06733       if (width > HOST_BITS_PER_WIDE_INT)
06734   {
06735     hi = TREE_INT_CST_HIGH (arg);
06736     if (width < 2 * HOST_BITS_PER_WIDE_INT)
06737       hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
06738   }
06739       else
06740   {
06741     hi = 0;
06742     if (width < HOST_BITS_PER_WIDE_INT)
06743       lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
06744   }
06745 
06746       switch (DECL_FUNCTION_CODE (fndecl))
06747   {
06748   case BUILT_IN_FFS:
06749   case BUILT_IN_FFSL:
06750   case BUILT_IN_FFSLL:
06751     if (lo != 0)
06752       result = exact_log2 (lo & -lo) + 1;
06753     else if (hi != 0)
06754       result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
06755     else
06756       result = 0;
06757     break;
06758 
06759   case BUILT_IN_CLZ:
06760   case BUILT_IN_CLZL:
06761   case BUILT_IN_CLZLL:
06762     if (hi != 0)
06763       result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
06764     else if (lo != 0)
06765       result = width - floor_log2 (lo) - 1;
06766     else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
06767       result = width;
06768     break;
06769 
06770   case BUILT_IN_CTZ:
06771   case BUILT_IN_CTZL:
06772   case BUILT_IN_CTZLL:
06773     if (lo != 0)
06774       result = exact_log2 (lo & -lo);
06775     else if (hi != 0)
06776       result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
06777     else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
06778       result = width;
06779     break;
06780 
06781   case BUILT_IN_POPCOUNT:
06782   case BUILT_IN_POPCOUNTL:
06783   case BUILT_IN_POPCOUNTLL:
06784     result = 0;
06785     while (lo)
06786       result++, lo &= lo - 1;
06787     while (hi)
06788       result++, hi &= hi - 1;
06789     break;
06790 
06791   case BUILT_IN_PARITY:
06792   case BUILT_IN_PARITYL:
06793   case BUILT_IN_PARITYLL:
06794     result = 0;
06795     while (lo)
06796       result++, lo &= lo - 1;
06797     while (hi)
06798       result++, hi &= hi - 1;
06799     result &= 1;
06800     break;
06801 
06802   default:
06803     gcc_unreachable ();
06804   }
06805 
06806       return build_int_cst (TREE_TYPE (exp), result);
06807     }
06808 
06809   return NULL_TREE;
06810 }
06811 
06812 /* Return true if EXPR is the real constant contained in VALUE.  */
06813 
06814 static bool
06815 real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
06816 {
06817   STRIP_NOPS (expr);
06818 
06819   return ((TREE_CODE (expr) == REAL_CST
06820            && ! TREE_CONSTANT_OVERFLOW (expr)
06821            && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
06822           || (TREE_CODE (expr) == COMPLEX_CST
06823               && real_dconstp (TREE_REALPART (expr), value)
06824               && real_zerop (TREE_IMAGPART (expr))));
06825 }
06826 
06827 /* A subroutine of fold_builtin to fold the various logarithmic
06828    functions.  EXP is the CALL_EXPR of a call to a builtin logN
06829    function.  VALUE is the base of the logN function.  */
06830 
06831 static tree
06832 fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
06833 {
06834   tree arglist = TREE_OPERAND (exp, 1);
06835 
06836   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
06837     {
06838       tree fndecl = get_callee_fndecl (exp);
06839       tree type = TREE_TYPE (TREE_TYPE (fndecl));
06840       tree arg = TREE_VALUE (arglist);
06841       const enum built_in_function fcode = builtin_mathfn_code (arg);
06842 
06843       /* Optimize logN(1.0) = 0.0.  */
06844       if (real_onep (arg))
06845   return build_real (type, dconst0);
06846 
06847       /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
06848          exactly, then only do this if flag_unsafe_math_optimizations.  */
06849       if (exact_real_truncate (TYPE_MODE (type), value)
06850     || flag_unsafe_math_optimizations)
06851         {
06852     const REAL_VALUE_TYPE value_truncate =
06853       real_value_truncate (TYPE_MODE (type), *value);
06854     if (real_dconstp (arg, &value_truncate))
06855       return build_real (type, dconst1);
06856   }
06857 
06858       /* Special case, optimize logN(expN(x)) = x.  */
06859       if (flag_unsafe_math_optimizations
06860     && ((value == &dconste
06861          && (fcode == BUILT_IN_EXP
06862        || fcode == BUILT_IN_EXPF
06863        || fcode == BUILT_IN_EXPL))
06864         || (value == &dconst2
06865       && (fcode == BUILT_IN_EXP2
06866           || fcode == BUILT_IN_EXP2F
06867           || fcode == BUILT_IN_EXP2L))
06868         || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
06869   return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
06870 
06871       /* Optimize logN(func()) for various exponential functions.  We
06872          want to determine the value "x" and the power "exponent" in
06873          order to transform logN(x**exponent) into exponent*logN(x).  */
06874       if (flag_unsafe_math_optimizations)
06875         {
06876     tree exponent = 0, x = 0;
06877 
06878     switch (fcode)
06879     {
06880     case BUILT_IN_EXP:
06881     case BUILT_IN_EXPF:
06882     case BUILT_IN_EXPL:
06883       /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
06884       x = build_real (type,
06885           real_value_truncate (TYPE_MODE (type), dconste));
06886       exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
06887       break;
06888     case BUILT_IN_EXP2:
06889     case BUILT_IN_EXP2F:
06890     case BUILT_IN_EXP2L:
06891       /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
06892       x = build_real (type, dconst2);
06893       exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
06894       break;
06895     case BUILT_IN_EXP10:
06896     case BUILT_IN_EXP10F:
06897     case BUILT_IN_EXP10L:
06898     case BUILT_IN_POW10:
06899     case BUILT_IN_POW10F:
06900     case BUILT_IN_POW10L:
06901       /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
06902       x = build_real (type, dconst10);
06903       exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
06904       break;
06905     case BUILT_IN_SQRT:
06906     case BUILT_IN_SQRTF:
06907     case BUILT_IN_SQRTL:
06908       /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
06909       x = TREE_VALUE (TREE_OPERAND (arg, 1));
06910       exponent = build_real (type, dconsthalf);
06911       break;
06912     case BUILT_IN_CBRT:
06913     case BUILT_IN_CBRTF:
06914     case BUILT_IN_CBRTL:
06915       /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
06916       x = TREE_VALUE (TREE_OPERAND (arg, 1));
06917       exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
06918                     dconstthird));
06919       break;
06920     case BUILT_IN_POW:
06921     case BUILT_IN_POWF:
06922     case BUILT_IN_POWL:
06923       /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
06924       x = TREE_VALUE (TREE_OPERAND (arg, 1));
06925       exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
06926       break;
06927     default:
06928       break;
06929     }
06930 
06931     /* Now perform the optimization.  */
06932     if (x && exponent)
06933       {
06934         tree logfn;
06935         arglist = build_tree_list (NULL_TREE, x);
06936         logfn = build_function_call_expr (fndecl, arglist);
06937         return fold (build2 (MULT_EXPR, type, exponent, logfn));
06938       }
06939   }
06940     }
06941 
06942   return 0;
06943 }
06944 
06945 /* Fold a builtin function call to pow, powf, or powl.  Return
06946    NULL_TREE if no simplification can be made.  */
06947 static tree
06948 fold_builtin_pow (tree fndecl, tree arglist, tree type)
06949 {
06950   enum built_in_function fcode;
06951   tree arg0 = TREE_VALUE (arglist);
06952   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
06953 
06954   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
06955     return NULL_TREE;
06956 
06957   /* Optimize pow(1.0,y) = 1.0.  */
06958   if (real_onep (arg0))
06959     return omit_one_operand (type, build_real (type, dconst1), arg1);
06960 
06961   if (TREE_CODE (arg1) == REAL_CST
06962       && ! TREE_CONSTANT_OVERFLOW (arg1))
06963     {
06964       REAL_VALUE_TYPE cint;
06965       REAL_VALUE_TYPE c;
06966       HOST_WIDE_INT n;
06967 
06968       c = TREE_REAL_CST (arg1);
06969 
06970       /* Optimize pow(x,0.0) = 1.0.  */
06971       if (REAL_VALUES_EQUAL (c, dconst0))
06972   return omit_one_operand (type, build_real (type, dconst1),
06973          arg0);
06974 
06975       /* Optimize pow(x,1.0) = x.  */
06976       if (REAL_VALUES_EQUAL (c, dconst1))
06977   return arg0;
06978 
06979       /* Optimize pow(x,-1.0) = 1.0/x.  */
06980       if (REAL_VALUES_EQUAL (c, dconstm1))
06981   return fold (build2 (RDIV_EXPR, type,
06982            build_real (type, dconst1), arg0));
06983 
06984       /* Optimize pow(x,0.5) = sqrt(x).  */
06985       if (flag_unsafe_math_optimizations
06986     && REAL_VALUES_EQUAL (c, dconsthalf))
06987   {
06988     tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
06989 
06990     if (sqrtfn != NULL_TREE)
06991       {
06992         tree arglist = build_tree_list (NULL_TREE, arg0);
06993         return build_function_call_expr (sqrtfn, arglist);
06994       }
06995   }
06996 
06997       /* Check for an integer exponent.  */
06998       n = real_to_integer (&c);
06999       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
07000       if (real_identical (&c, &cint))
07001   {
07002     /* Attempt to evaluate pow at compile-time.  */
07003     if (TREE_CODE (arg0) == REAL_CST
07004         && ! TREE_CONSTANT_OVERFLOW (arg0))
07005       {
07006         REAL_VALUE_TYPE x;
07007         bool inexact;
07008 
07009         x = TREE_REAL_CST (arg0);
07010         inexact = real_powi (&x, TYPE_MODE (type), &x, n);
07011         if (flag_unsafe_math_optimizations || !inexact)
07012     return build_real (type, x);
07013       }
07014 
07015     /* Strip sign ops from even integer powers.  */
07016     if ((n & 1) == 0 && flag_unsafe_math_optimizations)
07017       {
07018         tree narg0 = fold_strip_sign_ops (arg0);
07019         if (narg0)
07020     {
07021       arglist = build_tree_list (NULL_TREE, arg1);
07022       arglist = tree_cons (NULL_TREE, narg0, arglist);
07023       return build_function_call_expr (fndecl, arglist);
07024     }
07025       }
07026   }
07027     }
07028 
07029   /* Optimize pow(expN(x),y) = expN(x*y).  */
07030   fcode = builtin_mathfn_code (arg0);
07031   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
07032     {
07033       tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
07034       tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
07035       arg = fold (build2 (MULT_EXPR, type, arg, arg1));
07036       arglist = build_tree_list (NULL_TREE, arg);
07037       return build_function_call_expr (expfn, arglist);
07038     }
07039 
07040   /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
07041   if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode))
07042     {
07043       tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
07044       tree narg1 = fold (build2 (MULT_EXPR, type, arg1,
07045          build_real (type, dconsthalf)));
07046 
07047       arglist = tree_cons (NULL_TREE, narg0,
07048          build_tree_list (NULL_TREE, narg1));
07049       return build_function_call_expr (fndecl, arglist);
07050     }
07051 
07052   /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
07053   if (flag_unsafe_math_optimizations
07054       && (fcode == BUILT_IN_POW
07055     || fcode == BUILT_IN_POWF
07056     || fcode == BUILT_IN_POWL))
07057     {
07058       tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
07059       tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
07060       tree narg1 = fold (build2 (MULT_EXPR, type, arg01, arg1));
07061       arglist = tree_cons (NULL_TREE, arg00,
07062          build_tree_list (NULL_TREE, narg1));
07063       return build_function_call_expr (fndecl, arglist);
07064     }
07065   return NULL_TREE;
07066 }
07067 
07068 /* Fold a builtin function call to powi, powif, or powil.  Return
07069    NULL_TREE if no simplification can be made.  */
07070 static tree
07071