This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[LTO] PATCH: builtins.c/CALL_EXPR patch, take 2


OK, here's another attempt at hacking builtins.c to use the new CALL_EXPR abstractions. This time I changed all the fold_builtin_foo guys to take individual arguments instead of either an arglist or a CALL_EXPR, so that the common cases can all be dealt with without having to cons up temporary data structures on the heap.

OK to check in this time? I tested this as before.

-Sandra

2006-06-30  Sandra Loosemore  <sandra@codesourcery.com>

	* gcc/tree.c (init_call_expr_arg_iterator): Define.
	(first_call_expr_arg): Define.
	(next_call_expr_arg): Define.
	(more_call_expr_args_p): Define.
	(call_expr_nargs): Define.
	(call_expr_arg): Define.
	* gcc/tree.h (CALL_EXPR_FN, CALL_EXPR_STATIC_CHAIN, CALL_EXPR_ARGS):
	Define.
	(CALL_EXPR_ARG0, CALL_EXPR_ARG1, CALL_EXPR_ARG2):  Define.
	(call_expr_arg_iterator): Declare.
	(init_call_expr_arg_iterator): Declare.
	(first_call_expr_arg): Declare.
	(next_call_expr_arg): Declare.
	(more_call_expr_args_p): Declare.
	(call_expr_nargs): Declare.
	(call_expr_arg): Declare.
	(fold_call_expr): Declare new function replacing fold_builtin.
	(fold_builtin_next_arg): Add bool argument.
	(fold_build_call_expr): Declare.
	(build_call_expr):  Declare.
	* gcc/builtins.c (expand_builtin_setjmp): Change interfaces to
	all the expand_builtin_foo functions pass the whole CALL_EXPR instead
	of just its arglist, while the fold_builtin_foo functions get the
	individual arguments instead.  Use the new argument accessors.
	Update all callers.
	(expand_builtin_nonlocal_goto): Likewise.
	(expand_builtin_prefetch): Likewise.
	(expand_builtin_classify_type): Likewise.
	(expand_errno_check): Likewise.
	(expand_builtin_mathfn): Likewise.
	(expand_builtin_mathfn_2): Likewise.
	(expand_builtin_mathfn_3): Likewise.
	(expand_builtin_sincos): Likewise.
	(expand_builtin_int_roundingfn): Likewise.
	(expand_builtin_pow): Likewise.
	(expand_builtin_powi): Likewise.
	(expand_builtin_strstr): Likewise.
	(expand_builtin_strchr): Likewise.
	(expand_builtin_strrchr): Likewise.
	(expand_builtin_strpbrk): Likewise.
	(expand_builtin_memcpy): Likewise.
	(expand_builtin_mempcpy): Likewise.
	(expand_builtin_memmove): Likewise, plus split off new helper 
	function expand_builtin_memmove_args.
	(expand_builtin_bcopy): Likewise.
	(expand_builtin_strcpy): Likewise, plus split off new helper
	function expand_builtin_strcpy_args.
	(expand_builtin_stpcpy): Likewise.
	(expand_builtin_strncpy): Likewise.
	(expand_builtin_memset): Likewise, plus split off new helper
	function expand_builtin_memset_args.
	(expand_builtin_bzero): Likewise.
	(expand_builtin_memcmp): Likewise.
	(expand_builtin_strcmp): Likewise.
	(expand_builtin_strncmp): Likewise.
	(expand_builtin_strcat): Likewise.
	(expand_builtin_strncat): Likewise.
	(expand_builtin_strspn): Likewise.
	(expand_builtin_strcspn): Likewise.
	(expand_builtin_args_info): Likewise.
	(expand_builtin_va_start): Likewise.
	(expand_builtin_va_end): Likewise.
	(expand_builtin_va_copy): Likewise.
	(expand_builtin_frame_address): Likewise.
	(expand_builtin_alloca): Likewise.
	(expand_builtin_unop): Likewise.
	(expand_builtin_fputs): Likewise.
	(expand_builtin_expect): Likewise.
	(expand_builtin_expect_jump): Likewise.
	(expand_builtin_fabs): Likewise.
	(expand_builtin_copysign): Likewise.
	(expand_builtin_printf): Likewise.
	(expand_builtin_fprintf): Likewise.
	(expand_builtin_sprintf): Likewise.
	(expand_builtin_init_trampoline): Likewise.
	(expand_builtin_adjust_trampoline): Likewise.
	(expand_builtin_signbit): Likewise.
	(expand_builtin_fork_or_exec): Likewise.
	(expand_builtin_sync_operation): Likewise.
	(expand_builtin_compare_and_swap): Likewise.
	(expand_builtin_lock_test_and_set): Likewise.
	(expand_builtin_lock_release): Likewise.
	(expand_builtin): Likewise.
	(builtin_mathfn_code): Likewise.
	(fold_builtin_constant_p): Likewise.
	(fold_builtin_expect): Likewise.
	(fold_builtin_classify_type): Likewise.
	(fold_builtin_strlen): Likewise.
	(fold_builtin_nan): Likewise.
	(fold_trunc_transparent_mathfn): Likewise.
	(fold_fixed_mathfn): Likewise.
	(fold_builtin_cabs): Likewise.
	(fold_builtin_sqrt): Likewise.
	(fold_builtin_cbrt): Likewise.
	(fold_builtin_sin): Likewise.
	(fold_builtin_cos): Likewise.
	(fold_builtin_tan): Likewise.
	(fold_builtin_atan): Likewise.
	(fold_builtin_trunc): Likewise.
	(fold_builtin_floor): Likewise.
	(fold_builtin_ceil): Likewise.
	(fold_builtin_round): Likewise.
	(fold_builtin_int_roundingfn): Likewise.
	(fold_builtin_bitop): Likewise.
	(fold_builtin_logarithm): Likewise.
	(fold_builtin_pow): Likewise.
	(fold_builtin_powi): Likewise.
	(fold_builtin_exponent): Likewise.
	(fold_builtin_memcpy): Likewise.
	(fold_builtin_mempcpy): Likewise.
	(fold_builtin_memmove): Likewise.
	(fold_builtin_strcpy): Likewise.
	(fold_builtin_strncpy): Likewise.
	(fold_builtin_memcmp): Likewise.
	(fold_builtin_strcmp): Likewise.
	(fold_builtin_strncmp): Likewise.
	(fold_builtin_signbit): Likewise.
	(fold_builtin_copysign): Likewise.
	(fold_builtin_isascii): Likewise.
	(fold_builtin_toascii): Likewise.
	(fold_builtin_isdigit): Likewise.
	(fold_builtin_fabs): Likewise.
	(fold_builtin_abs): Likewise.
	(fold_builtin_classify): Likewise.
	(fold_builtin_unordered_cmp): Likewise.
	(fold_builtin_1): Likewise.  Split into new functions
	fold_builtin_n, fold_builtin_0, fold_builtin_1, fold_builtin_2,
	fold_builtin_3, fold_builtin_4, and fold_builtin_varargs, to dispatch
	based on the number of arguments.
	(fold_call_expr): New function replacing fold_builtin.
	(fold_build_call_expr): New function.
	(build_call_expr): New function.
	(rewrite_call_expr): New function.
	(validate_arg): New function.
	(validate_arglist): Rewrite to use new interfaces, as above.
	(fold_builtin_strstr): Likewise.
	(fold_builtin_strchr): Likewise.
	(fold_builtin_strrchr): Likewise.
	(fold_builtin_strpbrk): Likewise.
	(fold_builtin_strcat): Likewise.
	(fold_builtin_strncat): Likewise.
	(fold_builtin_strspn): Likewise.
	(fold_builtin_strcspn): Likewise.
	(fold_builtin_fputs): Likewise.
	(fold_builtin_next_arg): Likewise.  Also fix destructive
	modification of argument list, which seems like a Bad Idea.
	(fold_builtin_sprintf): Likewise.
	(expand_builtin_object_size): Likewise.
	(expand_builtin_memory_chk): Likewise.
	(maybe_emit_chk_warning): Likewise.
	(maybe_emit_sprintf_chk_warning): Likewise.
	(fold_builtin_object_size): Likewise.
	(fold_builtin_memory_chk): Likewise.
	(fold_builtin_stxcpy_chk): Likewise.
	(fold_builtin_strncpy_chk): Likewise.
	(fold_builtin_strcat_chk): Likewise.
	(fold_builtin_strncat_chk): Likewise.
	(fold_builtin_sprintf_chk): Likewise.
	(fold_builtin_snprintf_chk): Likewise.
	(fold_builtin_printf): Likewise.
	(fold_builtin_fprintf): Likewise.
	* gcc/fold-const.c (fold_ternary): Remove call to fold_builtin....
	(fold): ...and replace it with a call to fold_call_expr here.
	(fold_build3_stat): Use fold_build_call_expr to fold and construct
	CALL_EXPRs.
	* gcc/tree-ssa-ccp.c (ccp_fold): Use new arglist primitives and
	update calls to the various fold_builtin_foo functions to reflect
	their new interfaces.
	(ccp_fold_builtin): Likewise.
	* gcc/gimplify.c (gimplify_call_expr): Likewise.
	* gcc/except.c (expand_builtin_eh_return_data_regno): Change
	arguments to match other expand_builtin_foo functions.
	* gcc/tree-object-size.c (compute_object_sizes): Replace call to
	fold_builtin with fold_call_expr.


	
	



	

Index: gcc/tree.c
===================================================================
*** gcc/tree.c	(revision 115087)
--- gcc/tree.c	(working copy)
*************** stdarg_p (tree fntype)
*** 7603,7606 ****
--- 7603,7680 ----
  	      != void_type_node));
  }
  
+ /* Initialize the abstract argument list iterator object ITER with the argument
+    list from CALL_EXPR node EXP. */
+ 
+ void
+ init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
+ {
+   iter->tail =  CALL_EXPR_ARGS (exp);
+ }
+ 
+ /* Initialize the abstract argument list iterator object ITER, then advance
+    past and return the first argument.  Useful in for expressions, e.g.
+      for (arg = first_call_expr_arg (exp, &iter); arg;
+           arg = next_call_expr_arg (&iter))   */
+ 
+ tree
+ first_call_expr_arg (tree exp, call_expr_arg_iterator *iter)
+ {
+   init_call_expr_arg_iterator (exp, iter);
+   return next_call_expr_arg (iter);
+ }
+ 
+ /* Return the next argument from abstract argument list iterator object ITER,
+    and advance its state.  Returns NULL_TREE if there are no more arguments. */
+ 
+ tree
+ next_call_expr_arg (call_expr_arg_iterator *iter)
+ {
+   tree result;
+   if (iter->tail == NULL_TREE)
+     return NULL_TREE;
+   result = TREE_VALUE (iter->tail);
+   iter->tail = TREE_CHAIN (iter->tail);
+   return result;
+ }
+ 
+ /* Test whether there are more arguments in abstract argument list iterator
+    ITER, without changing its state.  */
+ 
+ bool
+ more_call_expr_args_p (const call_expr_arg_iterator *iter)
+ {
+   return (iter->tail != NULL_TREE);
+ }
+ 
+ /* Count the number of arguments passed in CALL_EXPR node EXP. */
+ int
+ call_expr_nargs (tree exp)
+ {
+   call_expr_arg_iterator iter;
+   int i = 0;
+   tree arg;
+   for (arg = first_call_expr_arg (exp, &iter); arg;
+        arg = next_call_expr_arg (&iter))
+     i++;
+   return i;
+ }
+ 
+ /* Return the Nth (zero-based) argument from CALL_EXPR node EXP.  Returns
+    NULL if there aren't that many arguments.  */
+ 
+ tree
+ call_expr_arg (tree exp, int n)
+ {
+   call_expr_arg_iterator iter;
+   tree t = NULL;
+   int i;
+   for (i = 0, t = first_call_expr_arg (exp, &iter);
+        (i < n) && t;
+        i++, t = next_call_expr_arg (&iter))
+     ;
+   return t;
+ }
+ 
+ 
  #include "gt-tree.h"
Index: gcc/tree.h
===================================================================
*** gcc/tree.h	(revision 115087)
--- gcc/tree.h	(working copy)
*************** struct tree_constructor GTY(())
*** 1533,1538 ****
--- 1533,1553 ----
  #define ASSERT_EXPR_VAR(NODE)	TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 0)
  #define ASSERT_EXPR_COND(NODE)	TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 1)
  
+ /* CALL_EXPR accessors.  */
+ #define CALL_EXPR_FN(NODE) TREE_OPERAND_CHECK_CODE ((NODE), CALL_EXPR, 0)
+ #define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND_CHECK_CODE ((NODE), CALL_EXPR, 2)
+ #define CALL_EXPR_ARGS(NODE) TREE_OPERAND_CHECK_CODE ((NODE), CALL_EXPR, 1)
+ #define CALL_EXPR_ARG0(NODE) TREE_VALUE (CALL_EXPR_ARGS (NODE))
+ #define CALL_EXPR_ARG1(NODE) TREE_VALUE (TREE_CHAIN (CALL_EXPR_ARGS (NODE)))
+ #define CALL_EXPR_ARG2(NODE) TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CALL_EXPR_ARGS (NODE))))
+ 
+ 
+ typedef struct call_expr_arg_iterator_d GTY (())
+ {
+   tree tail;
+ } call_expr_arg_iterator;
+ 
+ 
  /* OpenMP directive and clause accessors.  */
  
  #define OMP_BODY(NODE) \
*************** extern tree lower_bound_in_type (tree, t
*** 4135,4140 ****
--- 4150,4162 ----
  extern int operand_equal_for_phi_arg_p (tree, tree);
  extern bool empty_body_p (tree);
  extern bool stdarg_p (tree);
+ extern void init_call_expr_arg_iterator (tree, call_expr_arg_iterator *);
+ extern tree first_call_expr_arg (tree, call_expr_arg_iterator *);
+ extern tree next_call_expr_arg (call_expr_arg_iterator *);
+ extern bool more_call_expr_args_p (const call_expr_arg_iterator *);
+ extern int call_expr_nargs (tree);
+ extern tree call_expr_arg (tree, int);
+ 
  
  /* In stmt.c */
  
*************** extern enum tree_code invert_tree_compar
*** 4241,4259 ****
  extern bool tree_expr_nonzero_p (tree);
  
  /* In builtins.c */
! extern tree fold_builtin (tree, tree, bool);
! extern tree fold_builtin_fputs (tree, bool, bool, tree);
! extern tree fold_builtin_strcpy (tree, tree, tree);
! extern tree fold_builtin_strncpy (tree, tree, tree);
! extern tree fold_builtin_memory_chk (tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_stxcpy_chk (tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_strncpy_chk (tree, tree);
  extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
! extern bool fold_builtin_next_arg (tree);
  extern enum built_in_function builtin_mathfn_code (tree);
  extern tree build_function_call_expr (tree, tree);
  extern tree mathfn_built_in (tree, enum built_in_function fn);
  extern tree strip_float_extensions (tree);
  extern tree c_strlen (tree, int);
--- 4263,4283 ----
  extern bool tree_expr_nonzero_p (tree);
  
  /* In builtins.c */
! extern tree fold_call_expr (tree, bool);
! extern tree fold_builtin_fputs (tree, tree, bool, bool, tree);
! extern tree fold_builtin_strcpy (tree, tree, tree, tree);
! extern tree fold_builtin_strncpy (tree, tree, tree, tree, tree);
! extern tree fold_builtin_memory_chk (tree, tree, tree, tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_stxcpy_chk (tree, tree, tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_strncpy_chk (tree, tree, tree, tree, tree);
  extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
! extern bool fold_builtin_next_arg (tree, bool);
  extern enum built_in_function builtin_mathfn_code (tree);
  extern tree build_function_call_expr (tree, tree);
+ extern tree fold_build_call_expr (tree, tree, tree, tree);
+ extern tree build_call_expr (tree, int, ...);
  extern tree mathfn_built_in (tree, enum built_in_function fn);
  extern tree strip_float_extensions (tree);
  extern tree c_strlen (tree, int);
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c	(revision 115087)
--- gcc/builtins.c	(working copy)
*************** static rtx expand_builtin_next_arg (void
*** 101,107 ****
  static rtx expand_builtin_va_start (tree);
  static rtx expand_builtin_va_end (tree);
  static rtx expand_builtin_va_copy (tree);
! static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
  static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
  static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
  static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
--- 101,107 ----
  static rtx expand_builtin_va_start (tree);
  static rtx expand_builtin_va_end (tree);
  static rtx expand_builtin_va_copy (tree);
! static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
  static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
  static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
  static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
*************** static rtx expand_builtin_strncat (tree,
*** 110,131 ****
  static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
  static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
  static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
! static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
! static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
  static rtx expand_builtin_bcopy (tree);
  static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
  static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
  static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
  static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
! static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
  static rtx expand_builtin_bzero (tree);
  static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
! static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
! static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
! static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
  static rtx expand_builtin_alloca (tree, rtx);
  static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
  static rtx expand_builtin_frame_address (tree, tree);
--- 110,135 ----
  static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
  static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
  static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
! static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
! static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx, enum machine_mode, int);
! static rtx expand_builtin_memmove (tree, rtx, enum machine_mode);
! static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx, enum machine_mode, tree);
  static rtx expand_builtin_bcopy (tree);
  static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
+ static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode);
  static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
  static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
  static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
! static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
! static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
  static rtx expand_builtin_bzero (tree);
  static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
  static rtx expand_builtin_alloca (tree, rtx);
  static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
  static rtx expand_builtin_frame_address (tree, tree);
*************** static rtx expand_builtin_sprintf (tree,
*** 136,145 ****
--- 140,152 ----
  static tree stabilize_va_list (tree, int);
  static rtx expand_builtin_expect (tree, rtx);
  static tree fold_builtin_constant_p (tree);
+ static tree fold_builtin_expect (tree);
  static tree fold_builtin_classify_type (tree);
  static tree fold_builtin_strlen (tree);
  static tree fold_builtin_inf (tree, int);
  static tree fold_builtin_nan (tree, tree, int);
+ static tree rewrite_call_expr (tree, int, tree, int, ...);
+ static int validate_arg (tree, enum tree_code code);
  static int validate_arglist (tree, ...);
  static bool integer_valued_real_p (tree);
  static tree fold_trunc_transparent_mathfn (tree, tree);
*************** static rtx expand_builtin_signbit (tree,
*** 149,156 ****
  static tree fold_builtin_cabs (tree, tree);
  static tree fold_builtin_sqrt (tree, tree);
  static tree fold_builtin_cbrt (tree, tree);
! static tree fold_builtin_pow (tree, tree, tree);
! static tree fold_builtin_powi (tree, tree, tree);
  static tree fold_builtin_sin (tree);
  static tree fold_builtin_cos (tree, tree, tree);
  static tree fold_builtin_tan (tree);
--- 156,163 ----
  static tree fold_builtin_cabs (tree, tree);
  static tree fold_builtin_sqrt (tree, tree);
  static tree fold_builtin_cbrt (tree, tree);
! static tree fold_builtin_pow (tree, tree, tree, tree);
! static tree fold_builtin_powi (tree, tree, tree, tree);
  static tree fold_builtin_sin (tree);
  static tree fold_builtin_cos (tree, tree, tree);
  static tree fold_builtin_tan (tree);
*************** static tree fold_builtin_ceil (tree, tre
*** 161,204 ****
  static tree fold_builtin_round (tree, tree);
  static tree fold_builtin_int_roundingfn (tree, tree);
  static tree fold_builtin_bitop (tree, tree);
! static tree fold_builtin_memcpy (tree, tree);
! static tree fold_builtin_mempcpy (tree, tree, int);
! static tree fold_builtin_memmove (tree, tree);
! static tree fold_builtin_strchr (tree, tree);
! static tree fold_builtin_memcmp (tree);
! static tree fold_builtin_strcmp (tree);
! static tree fold_builtin_strncmp (tree);
  static tree fold_builtin_signbit (tree, tree);
! static tree fold_builtin_copysign (tree, tree, tree);
  static tree fold_builtin_isascii (tree);
  static tree fold_builtin_toascii (tree);
  static tree fold_builtin_isdigit (tree);
  static tree fold_builtin_fabs (tree, tree);
  static tree fold_builtin_abs (tree, tree);
! static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
  					enum tree_code);
  static tree fold_builtin_1 (tree, tree, bool);
! 
! static tree fold_builtin_strpbrk (tree, tree);
! static tree fold_builtin_strstr (tree, tree);
! static tree fold_builtin_strrchr (tree, tree);
! static tree fold_builtin_strcat (tree);
! static tree fold_builtin_strncat (tree);
! static tree fold_builtin_strspn (tree);
! static tree fold_builtin_strcspn (tree);
! static tree fold_builtin_sprintf (tree, int);
  
  static rtx expand_builtin_object_size (tree);
  static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
  				      enum built_in_function);
  static void maybe_emit_chk_warning (tree, enum built_in_function);
  static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
! static tree fold_builtin_object_size (tree);
! static tree fold_builtin_strcat_chk (tree, tree);
! static tree fold_builtin_strncat_chk (tree, tree);
  static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
! static tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
! static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
  static bool init_target_chars (void);
  
  static unsigned HOST_WIDE_INT target_newline;
--- 168,219 ----
  static tree fold_builtin_round (tree, tree);
  static tree fold_builtin_int_roundingfn (tree, tree);
  static tree fold_builtin_bitop (tree, tree);
! static tree fold_builtin_memcpy (tree, tree, tree, tree);
! static tree fold_builtin_mempcpy (tree, tree, tree, tree, int);
! static tree fold_builtin_memmove (tree, tree, tree, tree);
! static tree fold_builtin_strchr (tree, tree, tree);
! static tree fold_builtin_memcmp (tree, tree, tree);
! static tree fold_builtin_strcmp (tree, tree);
! static tree fold_builtin_strncmp (tree, tree, tree);
  static tree fold_builtin_signbit (tree, tree);
! static tree fold_builtin_copysign (tree, tree, tree, tree);
  static tree fold_builtin_isascii (tree);
  static tree fold_builtin_toascii (tree);
  static tree fold_builtin_isdigit (tree);
  static tree fold_builtin_fabs (tree, tree);
  static tree fold_builtin_abs (tree, tree);
! static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code,
  					enum tree_code);
+ static tree fold_builtin_n (tree, tree *, int, bool);
+ static tree fold_builtin_0 (tree, bool);
  static tree fold_builtin_1 (tree, tree, bool);
! static tree fold_builtin_2 (tree, tree, tree, bool);
! static tree fold_builtin_3 (tree, tree, tree, tree, bool);
! static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool);
! static tree fold_builtin_varargs (tree, tree, bool);
! 
! static tree fold_builtin_strpbrk (tree, tree, tree);
! static tree fold_builtin_strstr (tree, tree, tree);
! static tree fold_builtin_strrchr (tree, tree, tree);
! static tree fold_builtin_strcat (tree, tree);
! static tree fold_builtin_strncat (tree, tree, tree);
! static tree fold_builtin_strspn (tree, tree);
! static tree fold_builtin_strcspn (tree, tree);
! static tree fold_builtin_sprintf (tree, tree, tree, int);
  
  static rtx expand_builtin_object_size (tree);
  static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
  				      enum built_in_function);
  static void maybe_emit_chk_warning (tree, enum built_in_function);
  static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
! static tree fold_builtin_object_size (tree, tree);
! static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
! static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
  static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
! static tree fold_builtin_printf (tree, tree, tree, bool,
! 				 enum built_in_function);
! static tree fold_builtin_fprintf (tree, tree, tree, tree, bool,
! 				  enum built_in_function);
  static bool init_target_chars (void);
  
  static unsigned HOST_WIDE_INT target_newline;
*************** expand_builtin_setjmp_receiver (rtx rece
*** 703,720 ****
     them.  */
  
  static rtx
! expand_builtin_setjmp (tree arglist, rtx target)
  {
    rtx buf_addr, next_lab, cont_lab;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
    if (target == 0 || !REG_P (target)
        || REGNO (target) < FIRST_PSEUDO_REGISTER)
      target = gen_reg_rtx (TYPE_MODE (integer_type_node));
  
!   buf_addr = expand_normal (TREE_VALUE (arglist));
  
    next_lab = gen_label_rtx ();
    cont_lab = gen_label_rtx ();
--- 718,735 ----
     them.  */
  
  static rtx
! expand_builtin_setjmp (tree exp, rtx target)
  {
    rtx buf_addr, next_lab, cont_lab;
  
!   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
    if (target == 0 || !REG_P (target)
        || REGNO (target) < FIRST_PSEUDO_REGISTER)
      target = gen_reg_rtx (TYPE_MODE (integer_type_node));
  
!   buf_addr = expand_normal (CALL_EXPR_ARG0 (exp));
  
    next_lab = gen_label_rtx ();
    cont_lab = gen_label_rtx ();
*************** expand_builtin_longjmp (rtx buf_addr, rt
*** 844,860 ****
     and the address of the save area.  */
  
  static rtx
! expand_builtin_nonlocal_goto (tree arglist)
  {
    tree t_label, t_save_area;
    rtx r_label, r_save_area, r_fp, r_sp, insn;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   t_label = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
!   t_save_area = TREE_VALUE (arglist);
  
    r_label = expand_normal (t_label);
    r_label = convert_memory_address (Pmode, r_label);
--- 859,874 ----
     and the address of the save area.  */
  
  static rtx
! expand_builtin_nonlocal_goto (tree exp)
  {
    tree t_label, t_save_area;
    rtx r_label, r_save_area, r_fp, r_sp, insn;
  
!   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   t_label = CALL_EXPR_ARG0 (exp);
!   t_save_area = CALL_EXPR_ARG1 (exp);
  
    r_label = expand_normal (t_label);
    r_label = convert_memory_address (Pmode, r_label);
*************** expand_builtin_update_setjmp_buf (rtx bu
*** 954,984 ****
     effects.  */
  
  static void
! expand_builtin_prefetch (tree arglist)
  {
    tree arg0, arg1, arg2;
    rtx op0, op1, op2;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, 0))
      return;
  
!   arg0 = TREE_VALUE (arglist);
    /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
       zero (read) and argument 2 (locality) defaults to 3 (high degree of
       locality).  */
!   if (TREE_CHAIN (arglist))
!     {
!       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
!       if (TREE_CHAIN (TREE_CHAIN (arglist)))
! 	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
!       else
! 	arg2 = build_int_cst (NULL_TREE, 3);
!     }
    else
!     {
!       arg1 = integer_zero_node;
!       arg2 = build_int_cst (NULL_TREE, 3);
!     }
  
    /* Argument 0 is an address.  */
    op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
--- 968,995 ----
     effects.  */
  
  static void
! expand_builtin_prefetch (tree exp)
  {
    tree arg0, arg1, arg2;
+   int nargs;
    rtx op0, op1, op2;
  
!   if (!validate_arglist (exp, POINTER_TYPE, 0))
      return;
  
!   arg0 = CALL_EXPR_ARG0 (exp);
    /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
       zero (read) and argument 2 (locality) defaults to 3 (high degree of
       locality).  */
!   nargs = call_expr_nargs (exp);
!   if (nargs > 1)
!     arg1 = CALL_EXPR_ARG1 (exp);
!   else
!     arg1 = integer_zero_node;
!   if (nargs > 2)
!     arg2 = CALL_EXPR_ARG2 (exp);
    else
!     arg2 = build_int_cst (NULL_TREE, 3);
  
    /* Argument 0 is an address.  */
    op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
*************** type_to_class (tree type)
*** 1618,1631 ****
      }
  }
  
! /* Expand a call to __builtin_classify_type with arguments found in
!    ARGLIST.  */
  
  static rtx
! expand_builtin_classify_type (tree arglist)
  {
!   if (arglist != 0)
!     return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
    return GEN_INT (no_type_class);
  }
  
--- 1629,1641 ----
      }
  }
  
! /* Expand a call EXP to __builtin_classify_type.  */
  
  static rtx
! expand_builtin_classify_type (tree exp)
  {
!   if (call_expr_nargs (exp))
!     return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG0 (exp))));
    return GEN_INT (no_type_class);
  }
  
*************** expand_errno_check (tree exp, rtx target
*** 1756,1762 ****
  
  #ifdef TARGET_EDOM
    /* If this built-in doesn't throw an exception, set errno directly.  */
!   if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
      {
  #ifdef GEN_ERRNO_RTX
        rtx errno_rtx = GEN_ERRNO_RTX;
--- 1766,1772 ----
  
  #ifdef TARGET_EDOM
    /* If this built-in doesn't throw an exception, set errno directly.  */
!   if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
      {
  #ifdef GEN_ERRNO_RTX
        rtx errno_rtx = GEN_ERRNO_RTX;
*************** expand_errno_check (tree exp, rtx target
*** 1778,1784 ****
    emit_label (lab);
  }
  
- 
  /* Expand a call to one of the builtin math functions (sqrt, exp, or log).
     Return 0 if a normal call should be emitted rather than expanding the
     function in-line.  EXP is the expression that is a call to the builtin
--- 1788,1793 ----
*************** expand_builtin_mathfn (tree exp, rtx tar
*** 1791,1805 ****
    optab builtin_optab;
    rtx op0, insns, before_call;
    tree fndecl = get_callee_fndecl (exp);
-   tree arglist = TREE_OPERAND (exp, 1);
    enum machine_mode mode;
    bool errno_set = false;
    tree arg, narg;
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = TREE_VALUE (arglist);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
--- 1800,1813 ----
    optab builtin_optab;
    rtx op0, insns, before_call;
    tree fndecl = get_callee_fndecl (exp);
    enum machine_mode mode;
    bool errno_set = false;
    tree arg, narg;
  
!   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = CALL_EXPR_ARG0 (exp);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
*************** expand_builtin_mathfn (tree exp, rtx tar
*** 1873,1880 ****
        if (narg != arg)
  	{
  	  arg = narg;
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  exp = build_function_call_expr (fndecl, arglist);
  	}
  
        op0 = expand_expr (arg, subtarget, VOIDmode, 0);
--- 1881,1887 ----
        if (narg != arg)
  	{
  	  arg = narg;
! 	  exp = build_call_expr (fndecl, 1, arg);
  	}
  
        op0 = expand_expr (arg, subtarget, VOIDmode, 0);
*************** expand_builtin_mathfn_2 (tree exp, rtx t
*** 1963,1970 ****
    rtx op0, op1, insns;
    int op1_type = REAL_TYPE;
    tree fndecl = get_callee_fndecl (exp);
!   tree arglist = TREE_OPERAND (exp, 1);
!   tree arg0, arg1, temp, narg;
    enum machine_mode mode;
    bool errno_set = true;
    bool stable = true;
--- 1970,1976 ----
    rtx op0, op1, insns;
    int op1_type = REAL_TYPE;
    tree fndecl = get_callee_fndecl (exp);
!   tree arg0, arg1, narg;
    enum machine_mode mode;
    bool errno_set = true;
    bool stable = true;
*************** expand_builtin_mathfn_2 (tree exp, rtx t
*** 1974,1984 ****
        || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
      op1_type = INTEGER_TYPE;
  
!   if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
      return 0;
  
!   arg0 = TREE_VALUE (arglist);
!   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
--- 1980,1990 ----
        || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
      op1_type = INTEGER_TYPE;
  
!   if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
      return 0;
  
!   arg0 = CALL_EXPR_ARG0 (exp);
!   arg1 = CALL_EXPR_ARG1 (exp);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
*************** expand_builtin_mathfn_2 (tree exp, rtx t
*** 2013,2036 ****
    if (narg != arg1)
      {
        arg1 = narg;
-       temp = build_tree_list (NULL_TREE, narg);
        stable = false;
      }
-   else
-     temp = TREE_CHAIN (arglist);
- 
    narg = builtin_save_expr (arg0);
    if (narg != arg0)
      {
        arg0 = narg;
-       arglist = tree_cons (NULL_TREE, narg, temp);
        stable = false;
      }
-   else if (! stable)
-     arglist = tree_cons (NULL_TREE, arg0, temp);
  
    if (! stable)
!     exp = build_function_call_expr (fndecl, arglist);
  
    op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
    op1 = expand_normal (arg1);
--- 2019,2035 ----
    if (narg != arg1)
      {
        arg1 = narg;
        stable = false;
      }
    narg = builtin_save_expr (arg0);
    if (narg != arg0)
      {
        arg0 = narg;
        stable = false;
      }
  
    if (! stable)
!     exp = build_call_expr (fndecl, 2, arg0, arg1);
  
    op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
    op1 = expand_normal (arg1);
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2075,2088 ****
    optab builtin_optab;
    rtx op0, insns;
    tree fndecl = get_callee_fndecl (exp);
-   tree arglist = TREE_OPERAND (exp, 1);
    enum machine_mode mode;
    tree arg, narg;
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = TREE_VALUE (arglist);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
--- 2074,2086 ----
    optab builtin_optab;
    rtx op0, insns;
    tree fndecl = get_callee_fndecl (exp);
    enum machine_mode mode;
    tree arg, narg;
  
!   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = CALL_EXPR_ARG0 (exp);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2122,2129 ****
        if (narg != arg)
  	{
  	  arg = narg;
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  exp = build_function_call_expr (fndecl, arglist);
  	}
  
        op0 = expand_expr (arg, subtarget, VOIDmode, 0);
--- 2120,2126 ----
        if (narg != arg)
  	{
  	  arg = narg;
! 	  exp = build_call_expr (fndecl, 1, arg);
  	}
  
        op0 = expand_expr (arg, subtarget, VOIDmode, 0);
*************** static rtx
*** 2183,2200 ****
  expand_builtin_sincos (tree exp)
  {
    rtx op0, op1, op2, target1, target2;
-   tree arglist = TREE_OPERAND (exp, 1);
    enum machine_mode mode;
    tree arg, sinp, cosp;
    int result;
  
!   if (!validate_arglist (arglist, REAL_TYPE,
  			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
  
!   arg = TREE_VALUE (arglist);
!   sinp = TREE_VALUE (TREE_CHAIN (arglist));
!   cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
  
    /* Make a suitable register to place result in.  */
    mode = TYPE_MODE (TREE_TYPE (arg));
--- 2180,2196 ----
  expand_builtin_sincos (tree exp)
  {
    rtx op0, op1, op2, target1, target2;
    enum machine_mode mode;
    tree arg, sinp, cosp;
    int result;
  
!   if (!validate_arglist (exp, REAL_TYPE,
  			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
  
!   arg = CALL_EXPR_ARG0 (exp);
!   sinp = CALL_EXPR_ARG1 (exp);
!   cosp = CALL_EXPR_ARG2 (exp);
  
    /* Make a suitable register to place result in.  */
    mode = TYPE_MODE (TREE_TYPE (arg));
*************** expand_builtin_int_roundingfn (tree exp,
*** 2235,2250 ****
    optab builtin_optab;
    rtx op0, insns, tmp;
    tree fndecl = get_callee_fndecl (exp);
-   tree arglist = TREE_OPERAND (exp, 1);
    enum built_in_function fallback_fn;
    tree fallback_fndecl;
    enum machine_mode mode;
    tree arg, narg;
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      gcc_unreachable ();
  
!   arg = TREE_VALUE (arglist);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
--- 2231,2245 ----
    optab builtin_optab;
    rtx op0, insns, tmp;
    tree fndecl = get_callee_fndecl (exp);
    enum built_in_function fallback_fn;
    tree fallback_fndecl;
    enum machine_mode mode;
    tree arg, narg;
  
!   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
      gcc_unreachable ();
  
!   arg = CALL_EXPR_ARG0 (exp);
  
    switch (DECL_FUNCTION_CODE (fndecl))
      {
*************** expand_builtin_int_roundingfn (tree exp,
*** 2279,2286 ****
        if (narg != arg)
  	{
  	  arg = narg;
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  exp = build_function_call_expr (fndecl, arglist);
  	}
  
        op0 = expand_expr (arg, subtarget, VOIDmode, 0);
--- 2274,2280 ----
        if (narg != arg)
  	{
  	  arg = narg;
! 	  exp = build_call_expr (fndecl, 1, arg);
  	}
  
        op0 = expand_expr (arg, subtarget, VOIDmode, 0);
*************** expand_builtin_int_roundingfn (tree exp,
*** 2310,2316 ****
    /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
       ??? Perhaps convert (int)floorf(x) into (int)floor((double)x).  */
    gcc_assert (fallback_fndecl != NULL_TREE);
!   exp = build_function_call_expr (fallback_fndecl, arglist);
  
    tmp = expand_normal (exp);
  
--- 2304,2310 ----
    /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
       ??? Perhaps convert (int)floorf(x) into (int)floor((double)x).  */
    gcc_assert (fallback_fndecl != NULL_TREE);
!   exp = build_call_expr (fallback_fndecl, 1, arg);
  
    tmp = expand_normal (exp);
  
*************** expand_powi (rtx x, enum machine_mode mo
*** 2535,2548 ****
  static rtx
  expand_builtin_pow (tree exp, rtx target, rtx subtarget)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    tree arg0, arg1;
  
!   if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg0 = TREE_VALUE (arglist);
!   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
  
    if (TREE_CODE (arg1) == REAL_CST
        && ! TREE_CONSTANT_OVERFLOW (arg1))
--- 2529,2541 ----
  static rtx
  expand_builtin_pow (tree exp, rtx target, rtx subtarget)
  {
    tree arg0, arg1;
  
!   if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg0 = CALL_EXPR_ARG0 (exp);
!   arg1 = CALL_EXPR_ARG1 (exp);
  
    if (TREE_CODE (arg1) == REAL_CST
        && ! TREE_CONSTANT_OVERFLOW (arg1))
*************** expand_builtin_pow (tree exp, rtx target
*** 2585,2601 ****
  static rtx
  expand_builtin_powi (tree exp, rtx target, rtx subtarget)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    tree arg0, arg1;
    rtx op0, op1;
    enum machine_mode mode;
    enum machine_mode mode2;
  
!   if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
!   arg0 = TREE_VALUE (arglist);
!   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
    mode = TYPE_MODE (TREE_TYPE (exp));
  
    /* Handle constant power.  */
--- 2578,2593 ----
  static rtx
  expand_builtin_powi (tree exp, rtx target, rtx subtarget)
  {
    tree arg0, arg1;
    rtx op0, op1;
    enum machine_mode mode;
    enum machine_mode mode2;
  
!   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
!   arg0 = CALL_EXPR_ARG0 (exp);
!   arg1 = CALL_EXPR_ARG1 (exp);
    mode = TYPE_MODE (TREE_TYPE (exp));
  
    /* Handle constant power.  */
*************** expand_builtin_powi (tree exp, rtx targe
*** 2646,2660 ****
     try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strlen (tree arglist, rtx target,
  		       enum machine_mode target_mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
        rtx pat;
!       tree len, src = TREE_VALUE (arglist);
        rtx result, src_reg, char_rtx, before_strlen;
        enum machine_mode insn_mode = target_mode, char_mode;
        enum insn_code icode = CODE_FOR_nothing;
--- 2638,2652 ----
     try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strlen (tree exp, rtx target,
  		       enum machine_mode target_mode)
  {
!   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
        rtx pat;
!       tree len, src = CALL_EXPR_ARG0 (exp);
        rtx result, src_reg, char_rtx, before_strlen;
        enum machine_mode insn_mode = target_mode, char_mode;
        enum insn_code icode = CODE_FOR_nothing;
*************** expand_builtin_strlen (tree arglist, rtx
*** 2754,2764 ****
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strstr (arglist, type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 2746,2758 ----
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree type = TREE_TYPE (exp);
!       tree result = fold_builtin_strstr (CALL_EXPR_ARG0 (exp),
! 					 CALL_EXPR_ARG1 (exp), type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_strstr (tree arglist, tre
*** 2770,2780 ****
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strchr (arglist, type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
  
--- 2764,2776 ----
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree type = TREE_TYPE (exp);
!       tree result = fold_builtin_strchr (CALL_EXPR_ARG0 (exp),
! 					 CALL_EXPR_ARG1 (exp), type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
  
*************** expand_builtin_strchr (tree arglist, tre
*** 2788,2798 ****
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strrchr (arglist, type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 2784,2796 ----
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree type = TREE_TYPE (exp);
!       tree result = fold_builtin_strrchr (CALL_EXPR_ARG0 (exp),
! 					  CALL_EXPR_ARG1 (exp), type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_strrchr (tree arglist, tr
*** 2804,2814 ****
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strpbrk (arglist, type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 2802,2814 ----
     in TARGET, if convenient (and in mode MODE if that's convenient).  */
  
  static rtx
! expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree type = TREE_TYPE (exp);
!       tree result = fold_builtin_strpbrk (CALL_EXPR_ARG0 (exp),
! 					  CALL_EXPR_ARG1 (exp), type);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** builtin_memcpy_read_str (void *data, HOS
*** 2832,2838 ****
    return c_readstr (str + offset, mode);
  }
  
! /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
     Return 0 if we failed, the caller should emit a normal call,
     otherwise try to get the result in TARGET, if convenient (and in
     mode MODE if that's convenient).  */
--- 2832,2838 ----
    return c_readstr (str + offset, mode);
  }
  
! /* Expand a call EXP to the memcpy builtin.
     Return 0 if we failed, the caller should emit a normal call,
     otherwise try to get the result in TARGET, if convenient (and in
     mode MODE if that's convenient).  */
*************** static rtx
*** 2840,2860 ****
  expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
  {
    tree fndecl = get_callee_fndecl (exp);
!   tree arglist = TREE_OPERAND (exp, 1);
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dest = TREE_VALUE (arglist);
!       tree src = TREE_VALUE (TREE_CHAIN (arglist));
!       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
        const char *src_str;
        unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
        unsigned int dest_align
  	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
        rtx dest_mem, src_mem, dest_addr, len_rtx;
!       tree result = fold_builtin_memcpy (fndecl, arglist);
  
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 2840,2860 ----
  expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
  {
    tree fndecl = get_callee_fndecl (exp);
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dest = CALL_EXPR_ARG0 (exp);
!       tree src = CALL_EXPR_ARG1 (exp);
!       tree len = CALL_EXPR_ARG2 (exp);
        const char *src_str;
        unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
        unsigned int dest_align
  	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
        rtx dest_mem, src_mem, dest_addr, len_rtx;
!       tree result = fold_builtin_memcpy (dest, src, len,
! 					 TREE_TYPE (TREE_TYPE (fndecl)));
  
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_memcpy (tree exp, rtx tar
*** 2907,2913 ****
      }
  }
  
! /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
     Return 0 if we failed; the caller should emit a normal call,
     otherwise try to get the result in TARGET, if convenient (and in
     mode MODE if that's convenient).  If ENDP is 0 return the
--- 2907,2913 ----
      }
  }
  
! /* Expand a call EXP to the mempcpy builtin.
     Return 0 if we failed; the caller should emit a normal call,
     otherwise try to get the result in TARGET, if convenient (and in
     mode MODE if that's convenient).  If ENDP is 0 return the
*************** expand_builtin_memcpy (tree exp, rtx tar
*** 2916,2949 ****
     stpcpy.  */
  
  static rtx
! expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
! 			int endp)
  {
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    /* If return value is ignored, transform mempcpy into memcpy.  */
!   else if (target == const0_rtx)
      {
        tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
  
        if (!fn)
  	return 0;
  
!       return expand_expr (build_function_call_expr (fn, arglist),
  			  target, mode, EXPAND_NORMAL);
      }
    else
      {
-       tree dest = TREE_VALUE (arglist);
-       tree src = TREE_VALUE (TREE_CHAIN (arglist));
-       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
        const char *src_str;
        unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
        unsigned int dest_align
  	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
        rtx dest_mem, src_mem, len_rtx;
!       tree result = fold_builtin_mempcpy (arglist, type, endp);
  
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 2916,2960 ----
     stpcpy.  */
  
  static rtx
! expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
+   else
+     {
+       tree dest = CALL_EXPR_ARG0 (exp);
+       tree src = CALL_EXPR_ARG1 (exp);
+       tree len = CALL_EXPR_ARG2 (exp);
+       return expand_builtin_mempcpy_args (dest, src, len,
+ 					  TREE_TYPE (exp),
+ 					  target, mode, /*endp=*/ 1);
+     }
+ }
+ 
+ static rtx
+ expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type,
+ 			     rtx target, enum machine_mode mode, int endp)
+ {
    /* If return value is ignored, transform mempcpy into memcpy.  */
!   if (target == const0_rtx)
      {
        tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
  
        if (!fn)
  	return 0;
  
!       return expand_expr (build_call_expr (fn, 3, dest, src, len),
  			  target, mode, EXPAND_NORMAL);
      }
    else
      {
        const char *src_str;
        unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
        unsigned int dest_align
  	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
        rtx dest_mem, src_mem, len_rtx;
!       tree result = fold_builtin_mempcpy (dest, src, len, type, endp);
  
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_mempcpy (tree arglist, tr
*** 3002,3062 ****
     if we failed; the caller should emit a normal call.  */
  
  static rtx
! expand_builtin_memmove (tree arglist, tree type, rtx target,
! 			enum machine_mode mode, tree orig_exp)
  {
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dest = TREE_VALUE (arglist);
!       tree src = TREE_VALUE (TREE_CHAIN (arglist));
!       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
  
!       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
!       unsigned int dest_align
! 	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
!       tree result = fold_builtin_memmove (arglist, type);
  
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
  
!       /* If DEST is not a pointer type, call the normal function.  */
!       if (dest_align == 0)
! 	return 0;
  
!       /* If either SRC is not a pointer type, don't do this
! 	 operation in-line.  */
!       if (src_align == 0)
! 	return 0;
  
!       /* If src is categorized for a readonly section we can use
! 	 normal memcpy.  */
!       if (readonly_data_expr (src))
! 	{
! 	  tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
! 	  if (!fn)
! 	    return 0;
! 	  fn = build_function_call_expr (fn, arglist);
! 	  if (TREE_CODE (fn) == CALL_EXPR)
! 	    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
! 	  return expand_expr (fn, target, mode, EXPAND_NORMAL);
! 	}
  
!       /* If length is 1 and we can expand memcpy call inline,
! 	 it is ok to use memcpy as well.  */
!       if (integer_onep (len))
! 	{
! 	  rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
! 					    /*endp=*/0);
! 	  if (ret)
! 	    return ret;
! 	}
  
!       /* Otherwise, call the normal function.  */
!       return 0;
!    }
  }
  
  /* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
--- 3013,3082 ----
     if we failed; the caller should emit a normal call.  */
  
  static rtx
! expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dest = CALL_EXPR_ARG0 (exp);
!       tree src = CALL_EXPR_ARG1 (exp);
!       tree len = CALL_EXPR_ARG2 (exp);
  
!       return expand_builtin_memmove_args (dest, src, len,
! 					  TREE_TYPE (exp), target, mode, exp);
!     }
! }
  
! static rtx
! expand_builtin_memmove_args (tree dest, tree src, tree len,
! 			     tree type, rtx target,
! 			     enum machine_mode mode, tree orig_exp)
! {
!   unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
!   unsigned int dest_align
!     = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
!   tree result = fold_builtin_memmove (dest, src, len, type);
  
!   if (result)
!     return expand_expr (result, target, mode, EXPAND_NORMAL);
  
!   /* If DEST is not a pointer type, call the normal function.  */
!   if (dest_align == 0)
!     return 0;
  
!   /* If either SRC is not a pointer type, don't do this
!      operation in-line.  */
!   if (src_align == 0)
!     return 0;
  
!   /* If src is categorized for a readonly section we can use
!      normal memcpy.  */
!   if (readonly_data_expr (src))
!     {
!       tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
!       if (!fn)
! 	return 0;
!       fn = build_call_expr (fn, 3, dest, src, len);
!       if (TREE_CODE (fn) == CALL_EXPR)
! 	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
!       return expand_expr (fn, target, mode, EXPAND_NORMAL);
!     }
  
!   /* If length is 1 and we can expand memcpy call inline,
!      it is ok to use memcpy as well.  */
!   if (integer_onep (len))
!     {
!       rtx ret = expand_builtin_mempcpy_args (dest, src, len, type,
! 					     target, mode,
! 					     /*endp=*/0);
!       if (ret)
! 	return ret;
!     }
! 
!   /* Otherwise, call the normal function.  */
!   return 0;
  }
  
  /* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
*************** expand_builtin_memmove (tree arglist, tr
*** 3065,3092 ****
  static rtx
  expand_builtin_bcopy (tree exp)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    tree type = TREE_TYPE (exp);
!   tree src, dest, size, newarglist;
  
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   src = TREE_VALUE (arglist);
!   dest = TREE_VALUE (TREE_CHAIN (arglist));
!   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
  
    /* New argument list transforming bcopy(ptr x, ptr y, int z) to
       memmove(ptr y, ptr x, size_t z).   This is done this way
       so that if it isn't expanded inline, we fallback to
       calling bcopy instead of memmove.  */
  
!   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
!   newarglist = tree_cons (NULL_TREE, src, newarglist);
!   newarglist = tree_cons (NULL_TREE, dest, newarglist);
! 
!   return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
  }
  
  #ifndef HAVE_movstr
--- 3085,3109 ----
  static rtx
  expand_builtin_bcopy (tree exp)
  {
    tree type = TREE_TYPE (exp);
!   tree src, dest, size;
  
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   src = CALL_EXPR_ARG0 (exp);
!   dest = CALL_EXPR_ARG1 (exp);
!   size = CALL_EXPR_ARG2 (exp);
  
    /* New argument list transforming bcopy(ptr x, ptr y, int z) to
       memmove(ptr y, ptr x, size_t z).   This is done this way
       so that if it isn't expanded inline, we fallback to
       calling bcopy instead of memmove.  */
  
!   return expand_builtin_memmove_args (dest, src,
! 				      fold_convert (sizetype, size),
! 				      type, const0_rtx, VOIDmode, exp);
  }
  
  #ifndef HAVE_movstr
*************** expand_movstr (tree dest, tree src, rtx 
*** 3162,3183 ****
     convenient).  */
  
  static rtx
! expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strcpy (fndecl, arglist, 0);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
! 
!       return expand_movstr (TREE_VALUE (arglist),
! 			    TREE_VALUE (TREE_CHAIN (arglist)),
! 			    target, /*endp=*/0);
      }
    return 0;
  }
  
! /* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
     Return 0 if we failed the caller should emit a normal call,
     otherwise try to get the result in TARGET, if convenient (and in
     mode MODE if that's convenient).  */
--- 3179,3206 ----
     convenient).  */
  
  static rtx
! expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree dest = CALL_EXPR_ARG0 (exp);
!       tree src = CALL_EXPR_ARG1 (exp);
!       return expand_builtin_strcpy_args (fndecl, dest, src, target, mode);
      }
    return 0;
  }
  
! static rtx
! expand_builtin_strcpy_args (tree fndecl, tree dest, tree src,
! 			    rtx target, enum machine_mode mode)
! {
!   tree result = fold_builtin_strcpy (fndecl, dest, src, 0);
!   if (result)
!     return expand_expr (result, target, mode, EXPAND_NORMAL);
!   return expand_movstr (dest, src, target, /*endp=*/0);
! }
! 
! /* Expand a call EXP to the stpcpy builtin.
     Return 0 if we failed the caller should emit a normal call,
     otherwise try to get the result in TARGET, if convenient (and in
     mode MODE if that's convenient).  */
*************** expand_builtin_strcpy (tree fndecl, tree
*** 3185,3191 ****
  static rtx
  expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
  {
!   tree arglist = TREE_OPERAND (exp, 1);
    /* If return value is ignored, transform stpcpy into strcpy.  */
    if (target == const0_rtx)
      {
--- 3208,3220 ----
  static rtx
  expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
  {
!   tree dst, src;  
!   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
!     return 0;
! 
!   dst = CALL_EXPR_ARG0 (exp);
!   src = CALL_EXPR_ARG1 (exp);
! 
    /* If return value is ignored, transform stpcpy into strcpy.  */
    if (target == const0_rtx)
      {
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3193,3227 ****
        if (!fn)
  	return 0;
  
!       return expand_expr (build_function_call_expr (fn, arglist),
  			  target, mode, EXPAND_NORMAL);
      }
- 
-   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
-     return 0;
    else
      {
!       tree dst, src, len, lenp1;
!       tree narglist;
        rtx ret;
  
        /* Ensure we get an actual string whose length can be evaluated at
  	 compile-time, not an expression containing a string.  This is
  	 because the latter will potentially produce pessimized code
  	 when used to produce the return value.  */
-       src = TREE_VALUE (TREE_CHAIN (arglist));
        if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
! 	return expand_movstr (TREE_VALUE (arglist),
! 			      TREE_VALUE (TREE_CHAIN (arglist)),
! 			      target, /*endp=*/2);
  
-       dst = TREE_VALUE (arglist);
        lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
!       narglist = build_tree_list (NULL_TREE, lenp1);
!       narglist = tree_cons (NULL_TREE, src, narglist);
!       narglist = tree_cons (NULL_TREE, dst, narglist);
!       ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
! 				    target, mode, /*endp=*/2);
  
        if (ret)
  	return ret;
--- 3222,3245 ----
        if (!fn)
  	return 0;
  
!       return expand_expr (build_call_expr (fn, 2, dst, src),
  			  target, mode, EXPAND_NORMAL);
      }
    else
      {
!       tree len, lenp1;
        rtx ret;
  
        /* Ensure we get an actual string whose length can be evaluated at
  	 compile-time, not an expression containing a string.  This is
  	 because the latter will potentially produce pessimized code
  	 when used to produce the return value.  */
        if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
! 	return expand_movstr (dst, src, target, /*endp=*/2);
  
        lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
!       ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp),
! 					 target, mode, /*endp=*/2);
  
        if (ret)
  	return ret;
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3232,3239 ****
  
  	  if (GET_CODE (len_rtx) == CONST_INT)
  	    {
! 	      ret = expand_builtin_strcpy (get_callee_fndecl (exp),
! 					   arglist, target, mode);
  
  	      if (ret)
  		{
--- 3250,3257 ----
  
  	  if (GET_CODE (len_rtx) == CONST_INT)
  	    {
! 	      ret = expand_builtin_strcpy_args (get_callee_fndecl (exp),
! 						dst, src, target, mode);
  
  	      if (ret)
  		{
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3256,3264 ****
  	    }
  	}
  
!       return expand_movstr (TREE_VALUE (arglist),
! 			    TREE_VALUE (TREE_CHAIN (arglist)),
! 			    target, /*endp=*/2);
      }
  }
  
--- 3274,3280 ----
  	    }
  	}
  
!       return expand_movstr (dst, src, target, /*endp=*/2);
      }
  }
  
*************** static rtx
*** 3285,3297 ****
  expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
  {
    tree fndecl = get_callee_fndecl (exp);
!   tree arglist = TREE_OPERAND (exp, 1);
!   if (validate_arglist (arglist,
  			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
!       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
!       tree result = fold_builtin_strncpy (fndecl, arglist, slen);
  
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 3301,3314 ----
  expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
  {
    tree fndecl = get_callee_fndecl (exp);
!   if (validate_arglist (exp,
  			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree dest = CALL_EXPR_ARG0 (exp);
!       tree src = CALL_EXPR_ARG1 (exp);
!       tree slen = c_strlen (src, 1);
!       tree len = CALL_EXPR_ARG2 (exp);
!       tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen);
  
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_strncpy (tree exp, rtx ta
*** 3307,3316 ****
  	 use store_by_pieces, if it fails, punt.  */
        if (tree_int_cst_lt (slen, len))
  	{
- 	  tree dest = TREE_VALUE (arglist);
  	  unsigned int dest_align
  	    = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! 	  const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
  	  rtx dest_mem;
  
  	  if (!p || dest_align == 0 || !host_integerp (len, 1)
--- 3324,3332 ----
  	 use store_by_pieces, if it fails, punt.  */
        if (tree_int_cst_lt (slen, len))
  	{
  	  unsigned int dest_align
  	    = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! 	  const char *p = c_getstr (src);
  	  rtx dest_mem;
  
  	  if (!p || dest_align == 0 || !host_integerp (len, 1)
*************** builtin_memset_gen_str (void *data, HOST
*** 3379,3501 ****
     convenient).  */
  
  static rtx
! expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
! 		       tree orig_exp)
  {
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dest = TREE_VALUE (arglist);
!       tree val = TREE_VALUE (TREE_CHAIN (arglist));
!       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
!       tree fndecl, fn;
!       enum built_in_function fcode;
!       char c;
!       unsigned int dest_align;
!       rtx dest_mem, dest_addr, len_rtx;
! 
!       dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! 
!       /* If DEST is not a pointer type, don't do this
! 	 operation in-line.  */
!       if (dest_align == 0)
! 	return 0;
  
!       /* If the LEN parameter is zero, return DEST.  */
!       if (integer_zerop (len))
! 	{
! 	  /* Evaluate and ignore VAL in case it has side-effects.  */
! 	  expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  return expand_expr (dest, target, mode, EXPAND_NORMAL);
! 	}
  
!       /* Stabilize the arguments in case we fail.  */
!       dest = builtin_save_expr (dest);
!       val = builtin_save_expr (val);
!       len = builtin_save_expr (len);
  
!       len_rtx = expand_normal (len);
!       dest_mem = get_memory_rtx (dest, len);
  
!       if (TREE_CODE (val) != INTEGER_CST)
  	{
! 	  rtx val_rtx;
! 
! 	  val_rtx = expand_normal (val);
! 	  val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
! 				     val_rtx, 0);
! 
! 	  /* Assume that we can memset by pieces if we can store the
! 	   * the coefficients by pieces (in the required modes).
! 	   * We can't pass builtin_memset_gen_str as that emits RTL.  */
! 	  c = 1;
! 	  if (host_integerp (len, 1)
! 	      && !(optimize_size && tree_low_cst (len, 1) > 1)
! 	      && can_store_by_pieces (tree_low_cst (len, 1),
! 				      builtin_memset_read_str, &c, dest_align))
! 	    {
! 	      val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
! 				   val_rtx);
! 	      store_by_pieces (dest_mem, tree_low_cst (len, 1),
! 			       builtin_memset_gen_str, val_rtx, dest_align, 0);
! 	    }
! 	  else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
! 					    dest_align))
! 	    goto do_libcall;
! 
! 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
! 	  return dest_mem;
  	}
! 
!       if (target_char_cast (val, &c))
  	goto do_libcall;
  
!       if (c)
! 	{
! 	  if (host_integerp (len, 1)
! 	      && !(optimize_size && tree_low_cst (len, 1) > 1)
! 	      && can_store_by_pieces (tree_low_cst (len, 1),
! 				      builtin_memset_read_str, &c, dest_align))
! 	    store_by_pieces (dest_mem, tree_low_cst (len, 1),
! 			     builtin_memset_read_str, &c, dest_align, 0);
! 	  else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
! 					    dest_align))
! 	    goto do_libcall;
! 
! 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
! 	  return dest_mem;
! 	}
! 
!       set_mem_align (dest_mem, dest_align);
!       dest_addr = clear_storage (dest_mem, len_rtx,
! 				 CALL_EXPR_TAILCALL (orig_exp)
! 				 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
  
!       if (dest_addr == 0)
! 	{
! 	  dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! 	  dest_addr = convert_memory_address (ptr_mode, dest_addr);
! 	}
  
!       return dest_addr;
  
!     do_libcall:
!       fndecl = get_callee_fndecl (orig_exp);
!       fcode = DECL_FUNCTION_CODE (fndecl);
!       gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
!       arglist = build_tree_list (NULL_TREE, len);
!       if (fcode == BUILT_IN_MEMSET)
! 	arglist = tree_cons (NULL_TREE, val, arglist);
!       arglist = tree_cons (NULL_TREE, dest, arglist);
!       fn = build_function_call_expr (fndecl, arglist);
!       if (TREE_CODE (fn) == CALL_EXPR)
! 	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
!       return expand_call (fn, target, target == const0_rtx);
!     }
  }
  
  /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
--- 3395,3522 ----
     convenient).  */
  
  static rtx
! expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dest = CALL_EXPR_ARG0 (exp);
!       tree val = CALL_EXPR_ARG1 (exp);
!       tree len = CALL_EXPR_ARG2 (exp);
!       return expand_builtin_memset_args (dest, val, len, target, mode, exp);
!     }
! }
  
! static rtx
! expand_builtin_memset_args (tree dest, tree val, tree len,
! 			    rtx target, enum machine_mode mode, tree orig_exp)
! {
!   tree fndecl, fn;
!   enum built_in_function fcode;
!   char c;
!   unsigned int dest_align;
!   rtx dest_mem, dest_addr, len_rtx;
  
!   dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
  
!   /* If DEST is not a pointer type, don't do this operation in-line.  */
!   if (dest_align == 0)
!     return 0;
  
!   /* If the LEN parameter is zero, return DEST.  */
!   if (integer_zerop (len))
!     {
!       /* Evaluate and ignore VAL in case it has side-effects.  */
!       expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
!       return expand_expr (dest, target, mode, EXPAND_NORMAL);
!     }
! 
!   /* Stabilize the arguments in case we fail.  */
!   dest = builtin_save_expr (dest);
!   val = builtin_save_expr (val);
!   len = builtin_save_expr (len);
! 
!   len_rtx = expand_normal (len);
!   dest_mem = get_memory_rtx (dest, len);
! 
!   if (TREE_CODE (val) != INTEGER_CST)
!     {
!       rtx val_rtx;
! 
!       val_rtx = expand_normal (val);
!       val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
! 				 val_rtx, 0);
! 
!       /* Assume that we can memset by pieces if we can store the
!        * the coefficients by pieces (in the required modes).
!        * We can't pass builtin_memset_gen_str as that emits RTL.  */
!       c = 1;
!       if (host_integerp (len, 1)
! 	  && !(optimize_size && tree_low_cst (len, 1) > 1)
! 	  && can_store_by_pieces (tree_low_cst (len, 1),
! 				  builtin_memset_read_str, &c, dest_align))
  	{
! 	  val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
! 			       val_rtx);
! 	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
! 			   builtin_memset_gen_str, val_rtx, dest_align, 0);
  	}
!       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
! 					dest_align))
  	goto do_libcall;
+       
+       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+       dest_mem = convert_memory_address (ptr_mode, dest_mem);
+       return dest_mem;
+     }
+ 
+   if (target_char_cast (val, &c))
+     goto do_libcall;
+ 
+   if (c)
+     {
+       if (host_integerp (len, 1)
+ 	  && !(optimize_size && tree_low_cst (len, 1) > 1)
+ 	  && can_store_by_pieces (tree_low_cst (len, 1),
+ 				  builtin_memset_read_str, &c, dest_align))
+ 	store_by_pieces (dest_mem, tree_low_cst (len, 1),
+ 			 builtin_memset_read_str, &c, dest_align, 0);
+       else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
+ 					dest_align))
+ 	goto do_libcall;
+       
+       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+       dest_mem = convert_memory_address (ptr_mode, dest_mem);
+       return dest_mem;
+     }
  
!   set_mem_align (dest_mem, dest_align);
!   dest_addr = clear_storage (dest_mem, len_rtx,
! 			     CALL_EXPR_TAILCALL (orig_exp)
! 			     ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
  
!   if (dest_addr == 0)
!     {
!       dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
!       dest_addr = convert_memory_address (ptr_mode, dest_addr);
!     }
  
!   return dest_addr;
  
!  do_libcall:
!   fndecl = get_callee_fndecl (orig_exp);
!   fcode = DECL_FUNCTION_CODE (fndecl);
!   if (fcode == BUILT_IN_MEMSET)
!     fn = build_call_expr (fndecl, 3, dest, val, len);
!   else if (fcode == BUILT_IN_BZERO)
!     fn = build_call_expr (fndecl, 2, dest, len);
!   else
!     gcc_unreachable ();
!   if (TREE_CODE (fn) == CALL_EXPR)
!     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
!   return expand_call (fn, target, target == const0_rtx);
  }
  
  /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
*************** expand_builtin_memset (tree arglist, rtx
*** 3504,3558 ****
  static rtx
  expand_builtin_bzero (tree exp)
  {
!   tree arglist = TREE_OPERAND (exp, 1);
!   tree dest, size, newarglist;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   dest = TREE_VALUE (arglist);
!   size = TREE_VALUE (TREE_CHAIN (arglist));
  
    /* New argument list transforming bzero(ptr x, int y) to
       memset(ptr x, int 0, size_t y).   This is done this way
       so that if it isn't expanded inline, we fallback to
       calling bzero instead of memset.  */
  
!   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
!   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
!   newarglist = tree_cons (NULL_TREE, dest, newarglist);
! 
!   return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
  }
  
  /* Expand expression EXP, which is a call to the memcmp built-in function.
!    ARGLIST is the argument list for this call.  Return 0 if we failed and the
     caller should emit a normal call, otherwise try to get the result in
     TARGET, if convenient (and in mode MODE, if that's convenient).  */
  
  static rtx
! expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
! 		       enum machine_mode mode)
  {
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree result = fold_builtin_memcmp (arglist);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
  
  #if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
    {
-     tree arg1 = TREE_VALUE (arglist);
-     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
-     tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
      rtx arg1_rtx, arg2_rtx, arg3_rtx;
      rtx result;
      rtx insn;
  
      int arg1_align
        = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
      int arg2_align
--- 3525,3578 ----
  static rtx
  expand_builtin_bzero (tree exp)
  {
!   tree dest, size;
  
!   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   dest = CALL_EXPR_ARG0 (exp);
!   size = CALL_EXPR_ARG1 (exp);
  
    /* New argument list transforming bzero(ptr x, int y) to
       memset(ptr x, int 0, size_t y).   This is done this way
       so that if it isn't expanded inline, we fallback to
       calling bzero instead of memset.  */
  
!   return expand_builtin_memset_args (dest, integer_zero_node,
! 				     fold_convert (sizetype, size),
! 				     const0_rtx, VOIDmode, exp);
  }
  
  /* Expand expression EXP, which is a call to the memcmp built-in function.
!    Return 0 if we failed and the
     caller should emit a normal call, otherwise try to get the result in
     TARGET, if convenient (and in mode MODE, if that's convenient).  */
  
  static rtx
! expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree result = fold_builtin_memcmp (CALL_EXPR_ARG0 (exp),
! 					 CALL_EXPR_ARG1 (exp),
! 					 CALL_EXPR_ARG2 (exp));
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
  
  #if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
    {
      rtx arg1_rtx, arg2_rtx, arg3_rtx;
      rtx result;
      rtx insn;
  
+     tree arg1 = CALL_EXPR_ARG0 (exp);
+     tree arg2 = CALL_EXPR_ARG1 (exp);
+     tree len = CALL_EXPR_ARG2 (exp);
+ 
      int arg1_align
        = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
      int arg2_align
*************** expand_builtin_memcmp (tree exp ATTRIBUT
*** 3642,3654 ****
  static rtx
  expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
  {
!   tree arglist = TREE_OPERAND (exp, 1);
! 
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree result = fold_builtin_strcmp (arglist);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 3662,3673 ----
  static rtx
  expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree result = fold_builtin_strcmp (CALL_EXPR_ARG0 (exp),
! 					 CALL_EXPR_ARG1 (exp));
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_strcmp (tree exp, rtx tar
*** 3661,3668 ****
        rtx result, insn = NULL_RTX;
        tree fndecl, fn;
  
!       tree arg1 = TREE_VALUE (arglist);
!       tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
        int arg1_align
  	= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
        int arg2_align
--- 3680,3687 ----
        rtx result, insn = NULL_RTX;
        tree fndecl, fn;
  
!       tree arg1 = CALL_EXPR_ARG0 (exp);
!       tree arg2 = CALL_EXPR_ARG1 (exp);
        int arg1_align
  	= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
        int arg2_align
*************** expand_builtin_strcmp (tree exp, rtx tar
*** 3775,3784 ****
  #ifdef HAVE_cmpstrnsi
      do_libcall:
  #endif
-       arglist = build_tree_list (NULL_TREE, arg2);
-       arglist = tree_cons (NULL_TREE, arg1, arglist);
        fndecl = get_callee_fndecl (exp);
!       fn = build_function_call_expr (fndecl, arglist);
        if (TREE_CODE (fn) == CALL_EXPR)
  	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
        return expand_call (fn, target, target == const0_rtx);
--- 3794,3801 ----
  #ifdef HAVE_cmpstrnsi
      do_libcall:
  #endif
        fndecl = get_callee_fndecl (exp);
!       fn = build_call_expr (fndecl, 2, arg1, arg2);
        if (TREE_CODE (fn) == CALL_EXPR)
  	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
        return expand_call (fn, target, target == const0_rtx);
*************** expand_builtin_strcmp (tree exp, rtx tar
*** 3794,3807 ****
  static rtx
  expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
  {
!   tree arglist = TREE_OPERAND (exp, 1);
! 
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree result = fold_builtin_strncmp (arglist);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 3811,3824 ----
  static rtx
  expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp,
  			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree result = fold_builtin_strncmp (CALL_EXPR_ARG0 (exp),
! 					  CALL_EXPR_ARG1 (exp),
! 					  CALL_EXPR_ARG2 (exp));
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3812,3820 ****
  #ifdef HAVE_cmpstrnsi
    if (HAVE_cmpstrnsi)
    {
!     tree arg1 = TREE_VALUE (arglist);
!     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
!     tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
      tree len, len1, len2;
      rtx arg1_rtx, arg2_rtx, arg3_rtx;
      rtx result, insn;
--- 3829,3837 ----
  #ifdef HAVE_cmpstrnsi
    if (HAVE_cmpstrnsi)
    {
!     tree arg1 = CALL_EXPR_ARG0 (exp);
!     tree arg2 = CALL_EXPR_ARG1 (exp);
!     tree arg3 = CALL_EXPR_ARG2 (exp);
      tree len, len1, len2;
      rtx arg1_rtx, arg2_rtx, arg3_rtx;
      rtx result, insn;
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3904,3914 ****
  
      /* Expand the library call ourselves using a stabilized argument
         list to avoid re-evaluating the function's arguments twice.  */
-     arglist = build_tree_list (NULL_TREE, len);
-     arglist = tree_cons (NULL_TREE, arg2, arglist);
-     arglist = tree_cons (NULL_TREE, arg1, arglist);
      fndecl = get_callee_fndecl (exp);
!     fn = build_function_call_expr (fndecl, arglist);
      if (TREE_CODE (fn) == CALL_EXPR)
        CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
      return expand_call (fn, target, target == const0_rtx);
--- 3921,3928 ----
  
      /* Expand the library call ourselves using a stabilized argument
         list to avoid re-evaluating the function's arguments twice.  */
      fndecl = get_callee_fndecl (exp);
!     fn = build_call_expr (fndecl, 3, arg1, arg2, len);
      if (TREE_CODE (fn) == CALL_EXPR)
        CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
      return expand_call (fn, target, target == const0_rtx);
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3922,3935 ****
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dst = TREE_VALUE (arglist),
!       src = TREE_VALUE (TREE_CHAIN (arglist));
        const char *p = c_getstr (src);
  
        /* If the string length is zero, return the dst parameter.  */
--- 3936,3949 ----
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
!       tree dst = CALL_EXPR_ARG0 (exp),
!       src = CALL_EXPR_ARG1 (exp);
        const char *p = c_getstr (src);
  
        /* If the string length is zero, return the dst parameter.  */
*************** expand_builtin_strcat (tree fndecl, tree
*** 3945,3971 ****
  
  	  /* Stabilize the argument list.  */
  	  newsrc = builtin_save_expr (src);
- 	  if (newsrc != src)
- 	    arglist = build_tree_list (NULL_TREE, newsrc);
- 	  else
- 	    arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe.  */
- 
  	  dst = builtin_save_expr (dst);
  
  	  start_sequence ();
  
  	  /* Create strlen (dst).  */
! 	  newdst =
! 	    build_function_call_expr (strlen_fn,
! 				      build_tree_list (NULL_TREE, dst));
  	  /* Create (dst + (cast) strlen (dst)).  */
  	  newdst = fold_convert (TREE_TYPE (dst), newdst);
  	  newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
  
  	  newdst = builtin_save_expr (newdst);
- 	  arglist = tree_cons (NULL_TREE, newdst, arglist);
  
! 	  if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
  	    {
  	      end_sequence (); /* Stop sequence.  */
  	      return 0;
--- 3959,3977 ----
  
  	  /* Stabilize the argument list.  */
  	  newsrc = builtin_save_expr (src);
  	  dst = builtin_save_expr (dst);
  
  	  start_sequence ();
  
  	  /* Create strlen (dst).  */
! 	  newdst = build_call_expr (strlen_fn, 1, dst);
  	  /* Create (dst + (cast) strlen (dst)).  */
  	  newdst = fold_convert (TREE_TYPE (dst), newdst);
  	  newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
  
  	  newdst = builtin_save_expr (newdst);
  
! 	  if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode))
  	    {
  	      end_sequence (); /* Stop sequence.  */
  	      return 0;
*************** expand_builtin_strcat (tree fndecl, tree
*** 3988,3999 ****
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist,
  			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strncat (arglist);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 3994,4007 ----
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp,
  			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strncat (CALL_EXPR_ARG0 (exp),
! 					  CALL_EXPR_ARG1 (exp),
! 					  CALL_EXPR_ARG2 (exp));
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_strncat (tree arglist, rt
*** 4005,4015 ****
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strspn (arglist);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 4013,4024 ----
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strspn (CALL_EXPR_ARG0 (exp),
! 					 CALL_EXPR_ARG1 (exp));
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_strspn (tree arglist, rtx
*** 4021,4031 ****
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strcspn (arglist);
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
--- 4030,4041 ----
     otherwise try to get the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strcspn (CALL_EXPR_ARG0 (exp),
! 					  CALL_EXPR_ARG1 (exp));
        if (result)
  	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
*************** expand_builtin_saveregs (void)
*** 4074,4093 ****
     is controlled by the definition of CUMULATIVE_ARGS.  */
  
  static rtx
! expand_builtin_args_info (tree arglist)
  {
    int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
    int *word_ptr = (int *) &current_function_args_info;
  
    gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
  
!   if (arglist != 0)
      {
!       if (!host_integerp (TREE_VALUE (arglist), 0))
  	error ("argument of %<__builtin_args_info%> must be constant");
        else
  	{
! 	  HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
  
  	  if (wordnum < 0 || wordnum >= nwords)
  	    error ("argument of %<__builtin_args_info%> out of range");
--- 4084,4103 ----
     is controlled by the definition of CUMULATIVE_ARGS.  */
  
  static rtx
! expand_builtin_args_info (tree exp)
  {
    int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
    int *word_ptr = (int *) &current_function_args_info;
  
    gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
  
!   if (call_expr_nargs (exp) != 0)
      {
!       if (!host_integerp (CALL_EXPR_ARG0 (exp), 0))
  	error ("argument of %<__builtin_args_info%> must be constant");
        else
  	{
! 	  HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG0 (exp), 0);
  
  	  if (wordnum < 0 || wordnum >= nwords)
  	    error ("argument of %<__builtin_args_info%> out of range");
*************** std_expand_builtin_va_start (tree valist
*** 4180,4206 ****
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  }
  
! /* Expand ARGLIST, from a call to __builtin_va_start.  */
  
  static rtx
! expand_builtin_va_start (tree arglist)
  {
    rtx nextarg;
!   tree chain, valist;
  
!   chain = TREE_CHAIN (arglist);
! 
!   if (!chain)
      {
        error ("too few arguments to function %<va_start%>");
        return const0_rtx;
      }
  
!   if (fold_builtin_next_arg (chain))
      return const0_rtx;
  
    nextarg = expand_builtin_next_arg ();
!   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
  
  #ifdef EXPAND_BUILTIN_VA_START
    EXPAND_BUILTIN_VA_START (valist, nextarg);
--- 4190,4214 ----
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  }
  
! /* Expand EXP, a call to __builtin_va_start.  */
  
  static rtx
! expand_builtin_va_start (tree exp)
  {
    rtx nextarg;
!   tree valist;
  
!   if (call_expr_nargs (exp) < 2)
      {
        error ("too few arguments to function %<va_start%>");
        return const0_rtx;
      }
  
!   if (fold_builtin_next_arg (exp, true))
      return const0_rtx;
  
    nextarg = expand_builtin_next_arg ();
!   valist = stabilize_va_list (CALL_EXPR_ARG0 (exp), 1);
  
  #ifdef EXPAND_BUILTIN_VA_START
    EXPAND_BUILTIN_VA_START (valist, nextarg);
*************** gimplify_va_arg_expr (tree *expr_p, tree
*** 4382,4389 ****
        /* We can, however, treat "undefined" any way we please.
  	 Call abort to encourage the user to fix the program.  */
        inform ("if this code is reached, the program will abort");
!       t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
! 				    NULL);
        append_to_statement_list (t, pre_p);
  
        /* This is dead code, but go ahead and finish so that the
--- 4390,4396 ----
        /* We can, however, treat "undefined" any way we please.
  	 Call abort to encourage the user to fix the program.  */
        inform ("if this code is reached, the program will abort");
!       t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0);
        append_to_statement_list (t, pre_p);
  
        /* This is dead code, but go ahead and finish so that the
*************** gimplify_va_arg_expr (tree *expr_p, tree
*** 4421,4432 ****
      }
  }
  
! /* Expand ARGLIST, from a call to __builtin_va_end.  */
  
  static rtx
! expand_builtin_va_end (tree arglist)
  {
!   tree valist = TREE_VALUE (arglist);
  
    /* Evaluate for side effects, if needed.  I hate macros that don't
       do that.  */
--- 4428,4439 ----
      }
  }
  
! /* Expand EXP, a call to __builtin_va_end.  */
  
  static rtx
! expand_builtin_va_end (tree exp)
  {
!   tree valist = CALL_EXPR_ARG0 (exp);
  
    /* Evaluate for side effects, if needed.  I hate macros that don't
       do that.  */
*************** expand_builtin_va_end (tree arglist)
*** 4436,4452 ****
    return const0_rtx;
  }
  
! /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
     builtin rather than just as an assignment in stdarg.h because of the
     nastiness of array-type va_list types.  */
  
  static rtx
! expand_builtin_va_copy (tree arglist)
  {
    tree dst, src, t;
  
!   dst = TREE_VALUE (arglist);
!   src = TREE_VALUE (TREE_CHAIN (arglist));
  
    dst = stabilize_va_list (dst, 1);
    src = stabilize_va_list (src, 0);
--- 4443,4459 ----
    return const0_rtx;
  }
  
! /* Expand EXP, a call to __builtin_va_copy.  We do this as a
     builtin rather than just as an assignment in stdarg.h because of the
     nastiness of array-type va_list types.  */
  
  static rtx
! expand_builtin_va_copy (tree exp)
  {
    tree dst, src, t;
  
!   dst = CALL_EXPR_ARG0 (exp);
!   src = CALL_EXPR_ARG1 (exp);
  
    dst = stabilize_va_list (dst, 1);
    src = stabilize_va_list (src, 0);
*************** expand_builtin_va_copy (tree arglist)
*** 4489,4503 ****
     __builtin_return_address.  */
  
  static rtx
! expand_builtin_frame_address (tree fndecl, tree arglist)
  {
    /* The argument must be a nonnegative integer constant.
       It counts the number of frames to scan up the stack.
       The value is the return address saved in that frame.  */
!   if (arglist == 0)
      /* Warning about missing arg was already issued.  */
      return const0_rtx;
!   else if (! host_integerp (TREE_VALUE (arglist), 1))
      {
        if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
  	error ("invalid argument to %<__builtin_frame_address%>");
--- 4496,4510 ----
     __builtin_return_address.  */
  
  static rtx
! expand_builtin_frame_address (tree fndecl, tree exp)
  {
    /* The argument must be a nonnegative integer constant.
       It counts the number of frames to scan up the stack.
       The value is the return address saved in that frame.  */
!   if (call_expr_nargs (exp) == 0)
      /* Warning about missing arg was already issued.  */
      return const0_rtx;
!   else if (! host_integerp (CALL_EXPR_ARG0 (exp), 1))
      {
        if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
  	error ("invalid argument to %<__builtin_frame_address%>");
*************** expand_builtin_frame_address (tree fndec
*** 4509,4515 ****
      {
        rtx tem
  	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
! 				      tree_low_cst (TREE_VALUE (arglist), 1));
  
        /* Some ports cannot access arbitrary stack frames.  */
        if (tem == NULL)
--- 4516,4522 ----
      {
        rtx tem
  	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
! 				      tree_low_cst (CALL_EXPR_ARG0 (exp), 1));
  
        /* Some ports cannot access arbitrary stack frames.  */
        if (tem == NULL)
*************** expand_builtin_frame_address (tree fndec
*** 4532,4543 ****
      }
  }
  
! /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
     we failed and the caller should emit a normal call, otherwise try to get
     the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_alloca (tree arglist, rtx target)
  {
    rtx op0;
    rtx result;
--- 4539,4550 ----
      }
  }
  
! /* Expand EXP, a call to the alloca builtin.  Return 0 if
     we failed and the caller should emit a normal call, otherwise try to get
     the result in TARGET, if convenient.  */
  
  static rtx
! expand_builtin_alloca (tree exp, rtx target)
  {
    rtx op0;
    rtx result;
*************** expand_builtin_alloca (tree arglist, rtx
*** 4548,4558 ****
    if (flag_mudflap)
      return 0;
  
!   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
    /* Compute the argument.  */
!   op0 = expand_normal (TREE_VALUE (arglist));
  
    /* Allocate the desired space.  */
    result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
--- 4555,4565 ----
    if (flag_mudflap)
      return 0;
  
!   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
    /* Compute the argument.  */
!   op0 = expand_normal (CALL_EXPR_ARG0 (exp));
  
    /* Allocate the desired space.  */
    result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
*************** expand_builtin_alloca (tree arglist, rtx
*** 4561,4584 ****
    return result;
  }
  
! /* Expand a call to a unary builtin.  The arguments are in ARGLIST.
     Return 0 if a normal call should be emitted rather than expanding the
     function in-line.  If convenient, the result should be placed in TARGET.
     SUBTARGET may be used as the target for computing one of EXP's operands.  */
  
  static rtx
! expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
  		     rtx subtarget, optab op_optab)
  {
    rtx op0;
!   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
    /* Compute the argument.  */
!   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
    /* Compute op, into TARGET if possible.
       Set TARGET to wherever the result comes back.  */
!   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
  			op_optab, op0, target, 1);
    gcc_assert (target);
  
--- 4568,4591 ----
    return result;
  }
  
! /* Expand a call to a unary builtin in EXP.
     Return 0 if a normal call should be emitted rather than expanding the
     function in-line.  If convenient, the result should be placed in TARGET.
     SUBTARGET may be used as the target for computing one of EXP's operands.  */
  
  static rtx
! expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
  		     rtx subtarget, optab op_optab)
  {
    rtx op0;
!   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
    /* Compute the argument.  */
!   op0 = expand_expr (CALL_EXPR_ARG0 (exp), subtarget, VOIDmode, 0);
    /* Compute op, into TARGET if possible.
       Set TARGET to wherever the result comes back.  */
!   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG0 (exp))),
  			op_optab, op0, target, 1);
    gcc_assert (target);
  
*************** expand_builtin_unop (enum machine_mode t
*** 4589,4600 ****
     long, we attempt to transform this call into __builtin_fputc().  */
  
  static rtx
! expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
  {
    /* Verify the arguments in the original call.  */
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
  					unlocked, NULL_TREE);
        if (result)
  	return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
--- 4596,4609 ----
     long, we attempt to transform this call into __builtin_fputc().  */
  
  static rtx
! expand_builtin_fputs (tree exp, rtx target, bool unlocked)
  {
    /* Verify the arguments in the original call.  */
!   if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_fputs (CALL_EXPR_ARG0 (exp),
! 					CALL_EXPR_ARG1 (exp),
! 					(target == const0_rtx),
  					unlocked, NULL_TREE);
        if (result)
  	return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
*************** expand_builtin_fputs (tree arglist, rtx 
*** 4607,4622 ****
     a non-jump context.  */
  
  static rtx
! expand_builtin_expect (tree arglist, rtx target)
  {
!   tree exp, c;
    rtx note, rtx_c;
  
!   if (arglist == NULL_TREE
!       || TREE_CHAIN (arglist) == NULL_TREE)
      return const0_rtx;
!   exp = TREE_VALUE (arglist);
!   c = TREE_VALUE (TREE_CHAIN (arglist));
  
    if (TREE_CODE (c) != INTEGER_CST)
      {
--- 4616,4630 ----
     a non-jump context.  */
  
  static rtx
! expand_builtin_expect (tree exp, rtx target)
  {
!   tree arg, c;
    rtx note, rtx_c;
  
!   if (call_expr_nargs (exp) < 2)
      return const0_rtx;
!   arg = CALL_EXPR_ARG0 (exp);
!   c = CALL_EXPR_ARG1 (exp);
  
    if (TREE_CODE (c) != INTEGER_CST)
      {
*************** expand_builtin_expect (tree arglist, rtx
*** 4624,4630 ****
        c = integer_zero_node;
      }
  
!   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
  
    /* Don't bother with expected value notes for integral constants.  */
    if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
--- 4632,4638 ----
        c = integer_zero_node;
      }
  
!   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
  
    /* Don't bother with expected value notes for integral constants.  */
    if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
*************** expand_builtin_expect (tree arglist, rtx
*** 4653,4661 ****
  rtx
  expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
  {
!   tree arglist = TREE_OPERAND (exp, 1);
!   tree arg0 = TREE_VALUE (arglist);
!   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
    rtx ret = NULL_RTX;
  
    /* Only handle __builtin_expect (test, 0) and
--- 4661,4668 ----
  rtx
  expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
  {
!   tree arg0 = CALL_EXPR_ARG0 (exp);
!   tree arg1 = CALL_EXPR_ARG1 (exp);
    rtx ret = NULL_RTX;
  
    /* Only handle __builtin_expect (test, 0) and
*************** expand_builtin_trap (void)
*** 4773,4818 ****
    emit_barrier ();
  }
  
! /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
     Return 0 if a normal call should be emitted rather than expanding
     the function inline.  If convenient, the result should be placed
     in TARGET.  SUBTARGET may be used as the target for computing
     the operand.  */
  
  static rtx
! expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
  {
    enum machine_mode mode;
    tree arg;
    rtx op0;
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = TREE_VALUE (arglist);
    mode = TYPE_MODE (TREE_TYPE (arg));
    op0 = expand_expr (arg, subtarget, VOIDmode, 0);
    return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
  }
  
! /* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
     Return NULL is a normal call should be emitted rather than expanding the
     function inline.  If convenient, the result should be placed in TARGET.
     SUBTARGET may be used as the target for computing the operand.  */
  
  static rtx
! expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
  {
    rtx op0, op1;
    tree arg;
  
!   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = TREE_VALUE (arglist);
    op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
  
!   arg = TREE_VALUE (TREE_CHAIN (arglist));
    op1 = expand_normal (arg);
  
    return expand_copysign (op0, op1, target);
--- 4780,4825 ----
    emit_barrier ();
  }
  
! /* Expand EXP, a call to fabs, fabsf or fabsl.
     Return 0 if a normal call should be emitted rather than expanding
     the function inline.  If convenient, the result should be placed
     in TARGET.  SUBTARGET may be used as the target for computing
     the operand.  */
  
  static rtx
! expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
  {
    enum machine_mode mode;
    tree arg;
    rtx op0;
  
!   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = CALL_EXPR_ARG0 (exp);
    mode = TYPE_MODE (TREE_TYPE (arg));
    op0 = expand_expr (arg, subtarget, VOIDmode, 0);
    return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
  }
  
! /* Expand EXP, a call to copysign, copysignf, or copysignl.
     Return NULL is a normal call should be emitted rather than expanding the
     function inline.  If convenient, the result should be placed in TARGET.
     SUBTARGET may be used as the target for computing the operand.  */
  
  static rtx
! expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
  {
    rtx op0, op1;
    tree arg;
  
!   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = CALL_EXPR_ARG0 (exp);
    op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
  
!   arg = CALL_EXPR_ARG1 (exp);
    op1 = expand_normal (arg);
  
    return expand_copysign (op0, op1, target);
*************** static rtx
*** 4852,4858 ****
  expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
  		       bool unlocked)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    /* If we're using an unlocked function, assume the other unlocked
       functions exist explicitly.  */
    tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
--- 4859,4864 ----
*************** expand_builtin_printf (tree exp, rtx tar
*** 4860,4878 ****
    tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
      : implicit_built_in_decls[BUILT_IN_PUTS];
    const char *fmt_str;
!   tree fn, fmt, arg;
  
    /* If the return value is used, don't do the transformation.  */
    if (target != const0_rtx)
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
      return 0;
!   fmt = TREE_VALUE (arglist);
    if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
-   arglist = TREE_CHAIN (arglist);
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
--- 4866,4885 ----
    tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
      : implicit_built_in_decls[BUILT_IN_PUTS];
    const char *fmt_str;
!   tree fn = 0;
!   tree fmt, arg;
!   int nargs = call_expr_nargs (exp);
  
    /* If the return value is used, don't do the transformation.  */
    if (target != const0_rtx)
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (nargs == 0)
      return 0;
!   fmt = CALL_EXPR_ARG0 (exp);
    if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
*************** expand_builtin_printf (tree exp, rtx tar
*** 4885,4904 ****
    /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
    if (strcmp (fmt_str, target_percent_s_newline) == 0)
      {
!       if (! arglist
! 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       fn = fn_puts;
      }
    /* If the format specifier was "%c", call __builtin_putchar(arg).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if (! arglist
! 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       fn = fn_putchar;
      }
    else
      {
--- 4892,4911 ----
    /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
    if (strcmp (fmt_str, target_percent_s_newline) == 0)
      {
!       if ((nargs != 2)
! 	  || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG1 (exp))))
  	return 0;
!       if (fn_puts)
! 	fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG1 (exp));
      }
    /* If the format specifier was "%c", call __builtin_putchar(arg).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if ((nargs != 2)
! 	  || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG1 (exp))) != INTEGER_TYPE)
  	return 0;
!       if (fn_putchar)
! 	fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG1 (exp));
      }
    else
      {
*************** expand_builtin_printf (tree exp, rtx tar
*** 4906,4912 ****
        if (strchr (fmt_str, target_percent))
  	return 0;
  
!       if (arglist)
  	return 0;
  
        /* If the format specifier was "", printf does nothing.  */
--- 4913,4919 ----
        if (strchr (fmt_str, target_percent))
  	return 0;
  
!       if (nargs > 1)
  	return 0;
  
        /* If the format specifier was "", printf does nothing.  */
*************** expand_builtin_printf (tree exp, rtx tar
*** 4919,4926 ****
  	     convert "c"[0] to an int and pass that to the replacement
  	     function.  */
  	  arg = build_int_cst (NULL_TREE, fmt_str[0]);
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  fn = fn_putchar;
  	}
        else
  	{
--- 4926,4933 ----
  	     convert "c"[0] to an int and pass that to the replacement
  	     function.  */
  	  arg = build_int_cst (NULL_TREE, fmt_str[0]);
! 	  if (fn_putchar)
! 	    fn = build_call_expr (fn_putchar, 1, arg);
  	}
        else
  	{
*************** expand_builtin_printf (tree exp, rtx tar
*** 4933,4942 ****
  	      char *newstr = alloca (len);
  	      memcpy (newstr, fmt_str, len - 1);
  	      newstr[len - 1] = 0;
- 
  	      arg = build_string_literal (len, newstr);
! 	      arglist = build_tree_list (NULL_TREE, arg);
! 	      fn = fn_puts;
  	    }
  	  else
  	    /* We'd like to arrange to call fputs(string,stdout) here,
--- 4940,4948 ----
  	      char *newstr = alloca (len);
  	      memcpy (newstr, fmt_str, len - 1);
  	      newstr[len - 1] = 0;
  	      arg = build_string_literal (len, newstr);
! 	      if (fn_puts)
! 		fn = build_call_expr (fn_puts, 1, arg);
  	    }
  	  else
  	    /* We'd like to arrange to call fputs(string,stdout) here,
*************** expand_builtin_printf (tree exp, rtx tar
*** 4947,4953 ****
  
    if (!fn)
      return 0;
-   fn = build_function_call_expr (fn, arglist);
    if (TREE_CODE (fn) == CALL_EXPR)
      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    return expand_expr (fn, target, mode, EXPAND_NORMAL);
--- 4953,4958 ----
*************** static rtx
*** 4962,4968 ****
  expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
  			bool unlocked)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    /* If we're using an unlocked function, assume the other unlocked
       functions exist explicitly.  */
    tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
--- 4967,4972 ----
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 4970,4994 ****
    tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
      : implicit_built_in_decls[BUILT_IN_FPUTS];
    const char *fmt_str;
!   tree fn, fmt, fp, arg;
  
    /* If the return value is used, don't do the transformation.  */
    if (target != const0_rtx)
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
      return 0;
!   fp = TREE_VALUE (arglist);
    if (! POINTER_TYPE_P (TREE_TYPE (fp)))
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
!     return 0;
!   fmt = TREE_VALUE (arglist);
    if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
-   arglist = TREE_CHAIN (arglist);
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
--- 4974,4996 ----
    tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
      : implicit_built_in_decls[BUILT_IN_FPUTS];
    const char *fmt_str;
!   tree fn = 0;
!   tree fmt, fp, arg;
!   int nargs = call_expr_nargs (exp);
  
    /* If the return value is used, don't do the transformation.  */
    if (target != const0_rtx)
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (nargs < 2)
      return 0;
!   fp = CALL_EXPR_ARG0 (exp);
    if (! POINTER_TYPE_P (TREE_TYPE (fp)))
      return 0;
!   fmt = CALL_EXPR_ARG1 (exp);
    if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 5001,5026 ****
    /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
    if (strcmp (fmt_str, target_percent_s) == 0)
      {
!       if (! arglist
! 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       arg = TREE_VALUE (arglist);
!       arglist = build_tree_list (NULL_TREE, fp);
!       arglist = tree_cons (NULL_TREE, arg, arglist);
!       fn = fn_fputs;
      }
    /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if (! arglist
! 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       arg = TREE_VALUE (arglist);
!       arglist = build_tree_list (NULL_TREE, fp);
!       arglist = tree_cons (NULL_TREE, arg, arglist);
!       fn = fn_fputc;
      }
    else
      {
--- 5003,5024 ----
    /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
    if (strcmp (fmt_str, target_percent_s) == 0)
      {
!       if ((nargs != 3)
! 	  || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG2 (exp))))
  	return 0;
!       arg = CALL_EXPR_ARG2 (exp);
!       if (fn_fputs)
! 	fn = build_call_expr (fn_fputs, 2, arg, fp);
      }
    /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if ((nargs != 3)
! 	  || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG2 (exp))) != INTEGER_TYPE)
  	return 0;
!       arg = CALL_EXPR_ARG2 (exp);
!       if (fn_fputc)
! 	fn = build_call_expr (fn_fputc, 2, arg, fp);
      }
    else
      {
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 5028,5034 ****
        if (strchr (fmt_str, target_percent))
  	return 0;
  
!       if (arglist)
  	return 0;
  
        /* If the format specifier was "", fprintf does nothing.  */
--- 5026,5032 ----
        if (strchr (fmt_str, target_percent))
  	return 0;
  
!       if (nargs > 2)
  	return 0;
  
        /* If the format specifier was "", fprintf does nothing.  */
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 5042,5086 ****
        /* When "string" doesn't contain %, replace all cases of
  	 fprintf(stream,string) with fputs(string,stream).  The fputs
  	 builtin will take care of special cases like length == 1.  */
!       arglist = build_tree_list (NULL_TREE, fp);
!       arglist = tree_cons (NULL_TREE, fmt, arglist);
!       fn = fn_fputs;
      }
  
    if (!fn)
      return 0;
-   fn = build_function_call_expr (fn, arglist);
    if (TREE_CODE (fn) == CALL_EXPR)
      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    return expand_expr (fn, target, mode, EXPAND_NORMAL);
  }
  
! /* Expand a call to sprintf with argument list ARGLIST.  Return 0 if
     a normal call should be emitted rather than expanding the function
     inline.  If convenient, the result should be placed in TARGET with
     mode MODE.  */
  
  static rtx
! expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
  {
!   tree orig_arglist, dest, fmt;
    const char *fmt_str;
! 
!   orig_arglist = arglist;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
      return 0;
!   dest = TREE_VALUE (arglist);
    if (! POINTER_TYPE_P (TREE_TYPE (dest)))
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
!     return 0;
!   fmt = TREE_VALUE (arglist);
    if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
-   arglist = TREE_CHAIN (arglist);
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
--- 5040,5077 ----
        /* When "string" doesn't contain %, replace all cases of
  	 fprintf(stream,string) with fputs(string,stream).  The fputs
  	 builtin will take care of special cases like length == 1.  */
!       if (fn_fputs)
! 	fn = build_call_expr (fn_fputs, 2, fmt, fp);
      }
  
    if (!fn)
      return 0;
    if (TREE_CODE (fn) == CALL_EXPR)
      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    return expand_expr (fn, target, mode, EXPAND_NORMAL);
  }
  
! /* Expand a call EXP to sprintf.  Return 0 if
     a normal call should be emitted rather than expanding the function
     inline.  If convenient, the result should be placed in TARGET with
     mode MODE.  */
  
  static rtx
! expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
  {
!   tree dest, fmt;
    const char *fmt_str;
!   int nargs = call_expr_nargs (exp);
  
    /* Verify the required arguments in the original call.  */
!   if (nargs < 2)
      return 0;
!   dest = CALL_EXPR_ARG0 (exp);
    if (! POINTER_TYPE_P (TREE_TYPE (dest)))
      return 0;
!   fmt = CALL_EXPR_ARG0 (exp);
    if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
*************** expand_builtin_sprintf (tree arglist, rt
*** 5096,5104 ****
        tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
        tree exp;
  
!       if (arglist || ! fn)
  	return 0;
!       expand_expr (build_function_call_expr (fn, orig_arglist),
  		   const0_rtx, VOIDmode, EXPAND_NORMAL);
        if (target == const0_rtx)
  	return const0_rtx;
--- 5087,5095 ----
        tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
        tree exp;
  
!       if ((nargs > 2) || ! fn)
  	return 0;
!       expand_expr (build_call_expr (fn, 2, dest, fmt),
  		   const0_rtx, VOIDmode, EXPAND_NORMAL);
        if (target == const0_rtx)
  	return const0_rtx;
*************** expand_builtin_sprintf (tree arglist, rt
*** 5113,5122 ****
  
        if (! fn)
  	return 0;
! 
!       if (! arglist || TREE_CHAIN (arglist))
  	return 0;
!       arg = TREE_VALUE (arglist);
        if (! POINTER_TYPE_P (TREE_TYPE (arg)))
  	return 0;
  
--- 5104,5112 ----
  
        if (! fn)
  	return 0;
!       if (nargs != 3)
  	return 0;
!       arg = CALL_EXPR_ARG2 (exp);
        if (! POINTER_TYPE_P (TREE_TYPE (arg)))
  	return 0;
  
*************** expand_builtin_sprintf (tree arglist, rt
*** 5129,5137 ****
        else
  	len = NULL_TREE;
  
!       arglist = build_tree_list (NULL_TREE, arg);
!       arglist = tree_cons (NULL_TREE, dest, arglist);
!       expand_expr (build_function_call_expr (fn, arglist),
  		   const0_rtx, VOIDmode, EXPAND_NORMAL);
  
        if (target == const0_rtx)
--- 5119,5125 ----
        else
  	len = NULL_TREE;
  
!       expand_expr (build_call_expr (fn, 2, dest, arg),
  		   const0_rtx, VOIDmode, EXPAND_NORMAL);
  
        if (target == const0_rtx)
*************** round_trampoline_addr (rtx tramp)
*** 5192,5198 ****
  }
  
  static rtx
! expand_builtin_init_trampoline (tree arglist)
  {
    tree t_tramp, t_func, t_chain;
    rtx r_tramp, r_func, r_chain;
--- 5180,5186 ----
  }
  
  static rtx
! expand_builtin_init_trampoline (tree exp)
  {
    tree t_tramp, t_func, t_chain;
    rtx r_tramp, r_func, r_chain;
*************** expand_builtin_init_trampoline (tree arg
*** 5200,5214 ****
    rtx blktramp;
  #endif
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
  			 POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   t_tramp = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
!   t_func = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
!   t_chain = TREE_VALUE (arglist);
  
    r_tramp = expand_normal (t_tramp);
    r_func = expand_normal (t_func);
--- 5188,5200 ----
    rtx blktramp;
  #endif
  
!   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
  			 POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   t_tramp = CALL_EXPR_ARG0 (exp);
!   t_func = CALL_EXPR_ARG1 (exp);
!   t_chain = CALL_EXPR_ARG2 (exp);
  
    r_tramp = expand_normal (t_tramp);
    r_func = expand_normal (t_func);
*************** expand_builtin_init_trampoline (tree arg
*** 5229,5242 ****
  }
  
  static rtx
! expand_builtin_adjust_trampoline (tree arglist)
  {
    rtx tramp;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   tramp = expand_normal (TREE_VALUE (arglist));
    tramp = round_trampoline_addr (tramp);
  #ifdef TRAMPOLINE_ADJUST_ADDRESS
    TRAMPOLINE_ADJUST_ADDRESS (tramp);
--- 5215,5228 ----
  }
  
  static rtx
! expand_builtin_adjust_trampoline (tree exp)
  {
    rtx tramp;
  
!   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
      return NULL_RTX;
  
!   tramp = expand_normal (CALL_EXPR_ARG0 (exp));
    tramp = round_trampoline_addr (tramp);
  #ifdef TRAMPOLINE_ADJUST_ADDRESS
    TRAMPOLINE_ADJUST_ADDRESS (tramp);
*************** expand_builtin_signbit (tree exp, rtx ta
*** 5256,5270 ****
    const struct real_format *fmt;
    enum machine_mode fmode, imode, rmode;
    HOST_WIDE_INT hi, lo;
!   tree arg, arglist;
    int word, bitpos;
    rtx temp;
  
!   arglist = TREE_OPERAND (exp, 1);
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = TREE_VALUE (arglist);
    fmode = TYPE_MODE (TREE_TYPE (arg));
    rmode = TYPE_MODE (TREE_TYPE (exp));
    fmt = REAL_MODE_FORMAT (fmode);
--- 5242,5255 ----
    const struct real_format *fmt;
    enum machine_mode fmode, imode, rmode;
    HOST_WIDE_INT hi, lo;
!   tree arg;
    int word, bitpos;
    rtx temp;
  
!   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
      return 0;
  
!   arg = CALL_EXPR_ARG0 (exp);
    fmode = TYPE_MODE (TREE_TYPE (arg));
    rmode = TYPE_MODE (TREE_TYPE (exp));
    fmt = REAL_MODE_FORMAT (fmode);
*************** expand_builtin_signbit (tree exp, rtx ta
*** 5347,5358 ****
  }
  
  /* Expand fork or exec calls.  TARGET is the desired target of the
!    call.  ARGLIST is the list of arguments of the call.  FN is the
     identificator of the actual function.  IGNORE is nonzero if the
     value is to be ignored.  */
  
  static rtx
! expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
  {
    tree id, decl;
    tree call;
--- 5332,5343 ----
  }
  
  /* Expand fork or exec calls.  TARGET is the desired target of the
!    call.  EXP is the call. FN is the
     identificator of the actual function.  IGNORE is nonzero if the
     value is to be ignored.  */
  
  static rtx
! expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
  {
    tree id, decl;
    tree call;
*************** expand_builtin_fork_or_exec (tree fn, tr
*** 5406,5415 ****
    TREE_NOTHROW (decl) = 1;
    DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    DECL_VISIBILITY_SPECIFIED (decl) = 1;
!   call = build_function_call_expr (decl, arglist);
! 
    return expand_call (call, target, ignore);
! }
  
  
  /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
--- 5391,5400 ----
    TREE_NOTHROW (decl) = 1;
    DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    DECL_VISIBILITY_SPECIFIED (decl) = 1;
!   call = rewrite_call_expr (exp, 0, decl, 0);
    return expand_call (call, target, ignore);
!  }
!   
  
  
  /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
*************** get_builtin_sync_mem (tree loc, enum mac
*** 5451,5457 ****
  }
  
  /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
!    ARGLIST is the operands list to the function.  CODE is the rtx code
     that corresponds to the arithmetic or logical operation from the name;
     an exception here is that NOT actually means NAND.  TARGET is an optional
     place for us to store the results; AFTER is true if this is the
--- 5436,5442 ----
  }
  
  /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
!    EXP is the CALL_EXPR.  CODE is the rtx code
     that corresponds to the arithmetic or logical operation from the name;
     an exception here is that NOT actually means NAND.  TARGET is an optional
     place for us to store the results; AFTER is true if this is the
*************** get_builtin_sync_mem (tree loc, enum mac
*** 5459,5475 ****
     the result of the operation at all.  */
  
  static rtx
! expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
  			       enum rtx_code code, bool after,
  			       rtx target, bool ignore)
  {
    rtx val, mem;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
  
!   arglist = TREE_CHAIN (arglist);
!   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
  
    if (ignore)
      return expand_sync_operation (mem, val, code);
--- 5444,5459 ----
     the result of the operation at all.  */
  
  static rtx
! expand_builtin_sync_operation (enum machine_mode mode, tree exp,
  			       enum rtx_code code, bool after,
  			       rtx target, bool ignore)
  {
    rtx val, mem;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
  
!   val = expand_expr (CALL_EXPR_ARG1 (exp), NULL, mode, EXPAND_NORMAL);
  
    if (ignore)
      return expand_sync_operation (mem, val, code);
*************** expand_builtin_sync_operation (enum mach
*** 5478,5525 ****
  }
  
  /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
!    intrinsics.  ARGLIST is the operands list to the function.  IS_BOOL is
     true if this is the boolean form.  TARGET is a place for us to store the
     results; this is NOT optional if IS_BOOL is true.  */
  
  static rtx
! expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
  				 bool is_bool, rtx target)
  {
    rtx old_val, new_val, mem;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
! 
!   arglist = TREE_CHAIN (arglist);
!   old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
! 
!   arglist = TREE_CHAIN (arglist);
!   new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
  
    if (is_bool)
      return expand_bool_compare_and_swap (mem, old_val, new_val, target);
    else
      return expand_val_compare_and_swap (mem, old_val, new_val, target);
  }
  
  /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
     general form is actually an atomic exchange, and some targets only
     support a reduced form with the second argument being a constant 1.
!    ARGLIST is the operands list to the function; TARGET is an optional
     place for us to store the results.  */
  
  static rtx
! expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
  				  rtx target)
  {
    rtx val, mem;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
! 
!   arglist = TREE_CHAIN (arglist);
!   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
--- 5462,5504 ----
  }
  
  /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
!    intrinsics.  EXP is the CALL_EXPR.  IS_BOOL is
     true if this is the boolean form.  TARGET is a place for us to store the
     results; this is NOT optional if IS_BOOL is true.  */
  
  static rtx
! expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
  				 bool is_bool, rtx target)
  {
    rtx old_val, new_val, mem;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
!   old_val = expand_expr (CALL_EXPR_ARG1 (exp), NULL, mode, EXPAND_NORMAL);
!   new_val = expand_expr (CALL_EXPR_ARG2 (exp), NULL, mode, EXPAND_NORMAL);
  
    if (is_bool)
      return expand_bool_compare_and_swap (mem, old_val, new_val, target);
    else
      return expand_val_compare_and_swap (mem, old_val, new_val, target);
  }
+  
  
  /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
     general form is actually an atomic exchange, and some targets only
     support a reduced form with the second argument being a constant 1.
!    EXP is the CALL_EXPR; TARGET is an optional
     place for us to store the results.  */
  
  static rtx
! expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
  				  rtx target)
  {
    rtx val, mem;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
!   val = expand_expr (CALL_EXPR_ARG1 (exp), NULL, mode, EXPAND_NORMAL);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
*************** expand_builtin_synchronize (void)
*** 5547,5564 ****
    expand_asm_expr (x);
  }
  
! /* Expand the __sync_lock_release intrinsic.  ARGLIST is the operands list
!    to the function.  */
  
  static void
! expand_builtin_lock_release (enum machine_mode mode, tree arglist)
  {
    enum insn_code icode;
    rtx mem, insn;
    rtx val = const0_rtx;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
  
    /* If there is an explicit operation in the md file, use it.  */
    icode = sync_lock_release[mode];
--- 5526,5542 ----
    expand_asm_expr (x);
  }
  
! /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
  
  static void
! expand_builtin_lock_release (enum machine_mode mode, tree exp)
  {
    enum insn_code icode;
    rtx mem, insn;
    rtx val = const0_rtx;
  
    /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
  
    /* If there is an explicit operation in the md file, use it.  */
    icode = sync_lock_release[mode];
*************** expand_builtin (tree exp, rtx target, rt
*** 5592,5598 ****
  		int ignore)
  {
    tree fndecl = get_callee_fndecl (exp);
-   tree arglist = TREE_OPERAND (exp, 1);
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
  
--- 5570,5575 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 5620,5628 ****
      {
        bool volatilep = false;
        tree arg;
  
!       for (arg = arglist; arg; arg = TREE_CHAIN (arg))
! 	if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
  	  {
  	    volatilep = true;
  	    break;
--- 5597,5607 ----
      {
        bool volatilep = false;
        tree arg;
+       call_expr_arg_iterator iter;
  
!       for (arg = first_call_expr_arg (exp, &iter); arg;
! 	   arg = next_call_expr_arg (&iter))
! 	if (TREE_THIS_VOLATILE (arg))
  	  {
  	    volatilep = true;
  	    break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5630,5638 ****
  
        if (! volatilep)
  	{
! 	  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
! 	    expand_expr (TREE_VALUE (arg), const0_rtx,
! 			 VOIDmode, EXPAND_NORMAL);
  	  return const0_rtx;
  	}
      }
--- 5609,5617 ----
  
        if (! volatilep)
  	{
! 	  for (arg = first_call_expr_arg (exp, &iter); arg;
! 	       arg = next_call_expr_arg (&iter))
! 	    expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
  	  return const0_rtx;
  	}
      }
*************** expand_builtin (tree exp, rtx target, rt
*** 5640,5652 ****
    switch (fcode)
      {
      CASE_FLT_FN (BUILT_IN_FABS):
!       target = expand_builtin_fabs (arglist, target, subtarget);
        if (target)
  	return target;
        break;
  
      CASE_FLT_FN (BUILT_IN_COPYSIGN):
!       target = expand_builtin_copysign (arglist, target, subtarget);
        if (target)
  	return target;
        break;
--- 5619,5631 ----
    switch (fcode)
      {
      CASE_FLT_FN (BUILT_IN_FABS):
!       target = expand_builtin_fabs (exp, target, subtarget);
        if (target)
  	return target;
        break;
  
      CASE_FLT_FN (BUILT_IN_COPYSIGN):
!       target = expand_builtin_copysign (exp, target, subtarget);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5752,5770 ****
  	 computed?  We'll also need a safe worst case value for varargs
  	 functions.  */
      case BUILT_IN_APPLY:
!       if (!validate_arglist (arglist, POINTER_TYPE,
  			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
! 	  && !validate_arglist (arglist, REFERENCE_TYPE,
  				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
  	return const0_rtx;
        else
  	{
- 	  int i;
- 	  tree t;
  	  rtx ops[3];
  
! 	  for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
! 	    ops[i] = expand_normal (TREE_VALUE (t));
  
  	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
  	}
--- 5731,5748 ----
  	 computed?  We'll also need a safe worst case value for varargs
  	 functions.  */
      case BUILT_IN_APPLY:
!       if (!validate_arglist (exp, POINTER_TYPE,
  			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
! 	  && !validate_arglist (exp, REFERENCE_TYPE,
  				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
  	return const0_rtx;
        else
  	{
  	  rtx ops[3];
  
! 	  ops[0] = expand_normal (CALL_EXPR_ARG0 (exp));
! 	  ops[1] = expand_normal (CALL_EXPR_ARG1 (exp));
! 	  ops[2] = expand_normal (CALL_EXPR_ARG2 (exp));
  
  	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
  	}
*************** expand_builtin (tree exp, rtx target, rt
*** 5773,5808 ****
  	 value described by RESULT.  RESULT is address of the block of
  	 memory returned by __builtin_apply.  */
      case BUILT_IN_RETURN:
!       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
! 	expand_builtin_return (expand_normal (TREE_VALUE (arglist)));
        return const0_rtx;
  
      case BUILT_IN_SAVEREGS:
        return expand_builtin_saveregs ();
  
      case BUILT_IN_ARGS_INFO:
!       return expand_builtin_args_info (arglist);
  
        /* Return the address of the first anonymous stack arg.  */
      case BUILT_IN_NEXT_ARG:
!       if (fold_builtin_next_arg (arglist))
  	return const0_rtx;
        return expand_builtin_next_arg ();
  
      case BUILT_IN_CLASSIFY_TYPE:
!       return expand_builtin_classify_type (arglist);
  
      case BUILT_IN_CONSTANT_P:
        return const0_rtx;
  
      case BUILT_IN_FRAME_ADDRESS:
      case BUILT_IN_RETURN_ADDRESS:
!       return expand_builtin_frame_address (fndecl, arglist);
  
      /* Returns the address of the area where the structure is returned.
         0 otherwise.  */
      case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
!       if (arglist != 0
  	  || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
  	  || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
  	return const0_rtx;
--- 5751,5786 ----
  	 value described by RESULT.  RESULT is address of the block of
  	 memory returned by __builtin_apply.  */
      case BUILT_IN_RETURN:
!       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
! 	expand_builtin_return (expand_normal (CALL_EXPR_ARG0 (exp)));
        return const0_rtx;
  
      case BUILT_IN_SAVEREGS:
        return expand_builtin_saveregs ();
  
      case BUILT_IN_ARGS_INFO:
!       return expand_builtin_args_info (exp);
  
        /* Return the address of the first anonymous stack arg.  */
      case BUILT_IN_NEXT_ARG:
!       if (fold_builtin_next_arg (exp, false))
  	return const0_rtx;
        return expand_builtin_next_arg ();
  
      case BUILT_IN_CLASSIFY_TYPE:
!       return expand_builtin_classify_type (exp);
  
      case BUILT_IN_CONSTANT_P:
        return const0_rtx;
  
      case BUILT_IN_FRAME_ADDRESS:
      case BUILT_IN_RETURN_ADDRESS:
!       return expand_builtin_frame_address (fndecl, exp);
  
      /* Returns the address of the area where the structure is returned.
         0 otherwise.  */
      case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
!       if (call_expr_nargs (exp) != 0
  	  || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
  	  || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
  	return const0_rtx;
*************** expand_builtin (tree exp, rtx target, rt
*** 5810,5816 ****
  	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
  
      case BUILT_IN_ALLOCA:
!       target = expand_builtin_alloca (arglist, target);
        if (target)
  	return target;
        break;
--- 5788,5794 ----
  	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
  
      case BUILT_IN_ALLOCA:
!       target = expand_builtin_alloca (exp, target);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5819,5830 ****
        return expand_stack_save ();
  
      case BUILT_IN_STACK_RESTORE:
!       expand_stack_restore (TREE_VALUE (arglist));
        return const0_rtx;
  
      CASE_INT_FN (BUILT_IN_FFS):
      case BUILT_IN_FFSIMAX:
!       target = expand_builtin_unop (target_mode, arglist, target,
  				    subtarget, ffs_optab);
        if (target)
  	return target;
--- 5797,5808 ----
        return expand_stack_save ();
  
      case BUILT_IN_STACK_RESTORE:
!       expand_stack_restore (CALL_EXPR_ARG0 (exp));
        return const0_rtx;
  
      CASE_INT_FN (BUILT_IN_FFS):
      case BUILT_IN_FFSIMAX:
!       target = expand_builtin_unop (target_mode, exp, target,
  				    subtarget, ffs_optab);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 5832,5838 ****
  
      CASE_INT_FN (BUILT_IN_CLZ):
      case BUILT_IN_CLZIMAX:
!       target = expand_builtin_unop (target_mode, arglist, target,
  				    subtarget, clz_optab);
        if (target)
  	return target;
--- 5810,5816 ----
  
      CASE_INT_FN (BUILT_IN_CLZ):
      case BUILT_IN_CLZIMAX:
!       target = expand_builtin_unop (target_mode, exp, target,
  				    subtarget, clz_optab);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 5840,5846 ****
  
      CASE_INT_FN (BUILT_IN_CTZ):
      case BUILT_IN_CTZIMAX:
!       target = expand_builtin_unop (target_mode, arglist, target,
  				    subtarget, ctz_optab);
        if (target)
  	return target;
--- 5818,5824 ----
  
      CASE_INT_FN (BUILT_IN_CTZ):
      case BUILT_IN_CTZIMAX:
!       target = expand_builtin_unop (target_mode, exp, target,
  				    subtarget, ctz_optab);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 5848,5854 ****
  
      CASE_INT_FN (BUILT_IN_POPCOUNT):
      case BUILT_IN_POPCOUNTIMAX:
!       target = expand_builtin_unop (target_mode, arglist, target,
  				    subtarget, popcount_optab);
        if (target)
  	return target;
--- 5826,5832 ----
  
      CASE_INT_FN (BUILT_IN_POPCOUNT):
      case BUILT_IN_POPCOUNTIMAX:
!       target = expand_builtin_unop (target_mode, exp, target,
  				    subtarget, popcount_optab);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 5856,5875 ****
  
      CASE_INT_FN (BUILT_IN_PARITY):
      case BUILT_IN_PARITYIMAX:
!       target = expand_builtin_unop (target_mode, arglist, target,
  				    subtarget, parity_optab);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRLEN:
!       target = expand_builtin_strlen (arglist, target, target_mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRCPY:
!       target = expand_builtin_strcpy (fndecl, arglist, target, mode);
        if (target)
  	return target;
        break;
--- 5834,5853 ----
  
      CASE_INT_FN (BUILT_IN_PARITY):
      case BUILT_IN_PARITYIMAX:
!       target = expand_builtin_unop (target_mode, exp, target,
  				    subtarget, parity_optab);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRLEN:
!       target = expand_builtin_strlen (exp, target, target_mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRCPY:
!       target = expand_builtin_strcpy (fndecl, exp, target, mode);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5887,5937 ****
        break;
  
      case BUILT_IN_STRCAT:
!       target = expand_builtin_strcat (fndecl, arglist, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRNCAT:
!       target = expand_builtin_strncat (arglist, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRSPN:
!       target = expand_builtin_strspn (arglist, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRCSPN:
!       target = expand_builtin_strcspn (arglist, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRSTR:
!       target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRPBRK:
!       target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_INDEX:
      case BUILT_IN_STRCHR:
!       target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_RINDEX:
      case BUILT_IN_STRRCHR:
!       target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
        if (target)
  	return target;
        break;
--- 5865,5915 ----
        break;
  
      case BUILT_IN_STRCAT:
!       target = expand_builtin_strcat (fndecl, exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRNCAT:
!       target = expand_builtin_strncat (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRSPN:
!       target = expand_builtin_strspn (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRCSPN:
!       target = expand_builtin_strcspn (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRSTR:
!       target = expand_builtin_strstr (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_STRPBRK:
!       target = expand_builtin_strpbrk (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_INDEX:
      case BUILT_IN_STRCHR:
!       target = expand_builtin_strchr (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_RINDEX:
      case BUILT_IN_STRRCHR:
!       target = expand_builtin_strrchr (exp, target, mode);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5943,5956 ****
        break;
  
      case BUILT_IN_MEMPCPY:
!       target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_MEMMOVE:
!       target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
! 				       mode, exp);
        if (target)
  	return target;
        break;
--- 5921,5933 ----
        break;
  
      case BUILT_IN_MEMPCPY:
!       target = expand_builtin_mempcpy (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_MEMMOVE:
!       target = expand_builtin_memmove (exp, target, mode);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5962,5968 ****
        break;
  
      case BUILT_IN_MEMSET:
!       target = expand_builtin_memset (arglist, target, mode, exp);
        if (target)
  	return target;
        break;
--- 5939,5945 ----
        break;
  
      case BUILT_IN_MEMSET:
!       target = expand_builtin_memset (exp, target, mode);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5987,5999 ****
  
      case BUILT_IN_BCMP:
      case BUILT_IN_MEMCMP:
!       target = expand_builtin_memcmp (exp, arglist, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_SETJMP:
!       target = expand_builtin_setjmp (arglist, target);
        if (target)
  	return target;
        break;
--- 5964,5976 ----
  
      case BUILT_IN_BCMP:
      case BUILT_IN_MEMCMP:
!       target = expand_builtin_memcmp (exp, target, mode);
        if (target)
  	return target;
        break;
  
      case BUILT_IN_SETJMP:
!       target = expand_builtin_setjmp (exp, target);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6002,6014 ****
  	 It's similar to the C library longjmp function but works with
  	 __builtin_setjmp above.  */
      case BUILT_IN_LONGJMP:
!       if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
  	break;
        else
  	{
! 	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
  				      VOIDmode, EXPAND_NORMAL);
! 	  rtx value = expand_normal (TREE_VALUE (TREE_CHAIN (arglist)));
  
  	  if (value != const1_rtx)
  	    {
--- 5979,5991 ----
  	 It's similar to the C library longjmp function but works with
  	 __builtin_setjmp above.  */
      case BUILT_IN_LONGJMP:
!       if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
  	break;
        else
  	{
! 	  rtx buf_addr = expand_expr (CALL_EXPR_ARG0 (exp), subtarget,
  				      VOIDmode, EXPAND_NORMAL);
! 	  rtx value = expand_normal (CALL_EXPR_ARG1 (exp));
  
  	  if (value != const1_rtx)
  	    {
*************** expand_builtin (tree exp, rtx target, rt
*** 6021,6027 ****
  	}
  
      case BUILT_IN_NONLOCAL_GOTO:
!       target = expand_builtin_nonlocal_goto (arglist);
        if (target)
  	return target;
        break;
--- 5998,6004 ----
  	}
  
      case BUILT_IN_NONLOCAL_GOTO:
!       target = expand_builtin_nonlocal_goto (exp);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6029,6038 ****
        /* This updates the setjmp buffer that is its argument with the value
  	 of the current stack pointer.  */
      case BUILT_IN_UPDATE_SETJMP_BUF:
!       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
  	{
  	  rtx buf_addr
! 	    = expand_normal (TREE_VALUE (arglist));
  
  	  expand_builtin_update_setjmp_buf (buf_addr);
  	  return const0_rtx;
--- 6006,6015 ----
        /* This updates the setjmp buffer that is its argument with the value
  	 of the current stack pointer.  */
      case BUILT_IN_UPDATE_SETJMP_BUF:
!       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
  	{
  	  rtx buf_addr
! 	    = expand_normal (CALL_EXPR_ARG0 (exp));
  
  	  expand_builtin_update_setjmp_buf (buf_addr);
  	  return const0_rtx;
*************** expand_builtin (tree exp, rtx target, rt
*** 6056,6067 ****
        break;
  
      case BUILT_IN_FPUTS:
!       target = expand_builtin_fputs (arglist, target, false);
        if (target)
  	return target;
        break;
      case BUILT_IN_FPUTS_UNLOCKED:
!       target = expand_builtin_fputs (arglist, target, true);
        if (target)
  	return target;
        break;
--- 6033,6044 ----
        break;
  
      case BUILT_IN_FPUTS:
!       target = expand_builtin_fputs (exp, target, false);
        if (target)
  	return target;
        break;
      case BUILT_IN_FPUTS_UNLOCKED:
!       target = expand_builtin_fputs (exp, target, true);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6079,6085 ****
        break;
  
      case BUILT_IN_SPRINTF:
!       target = expand_builtin_sprintf (arglist, target, mode);
        if (target)
  	return target;
        break;
--- 6056,6062 ----
        break;
  
      case BUILT_IN_SPRINTF:
!       target = expand_builtin_sprintf (exp, target, mode);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6100,6134 ****
      case BUILT_IN_DWARF_SP_COLUMN:
        return expand_builtin_dwarf_sp_column ();
      case BUILT_IN_INIT_DWARF_REG_SIZES:
!       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
        return const0_rtx;
  #endif
      case BUILT_IN_FROB_RETURN_ADDR:
!       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
      case BUILT_IN_EXTRACT_RETURN_ADDR:
!       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
      case BUILT_IN_EH_RETURN:
!       expand_builtin_eh_return (TREE_VALUE (arglist),
! 				TREE_VALUE (TREE_CHAIN (arglist)));
        return const0_rtx;
  #ifdef EH_RETURN_DATA_REGNO
      case BUILT_IN_EH_RETURN_DATA_REGNO:
!       return expand_builtin_eh_return_data_regno (arglist);
  #endif
      case BUILT_IN_EXTEND_POINTER:
!       return expand_builtin_extend_pointer (TREE_VALUE (arglist));
  
      case BUILT_IN_VA_START:
      case BUILT_IN_STDARG_START:
!       return expand_builtin_va_start (arglist);
      case BUILT_IN_VA_END:
!       return expand_builtin_va_end (arglist);
      case BUILT_IN_VA_COPY:
!       return expand_builtin_va_copy (arglist);
      case BUILT_IN_EXPECT:
!       return expand_builtin_expect (arglist, target);
      case BUILT_IN_PREFETCH:
!       expand_builtin_prefetch (arglist);
        return const0_rtx;
  
      case BUILT_IN_PROFILE_FUNC_ENTER:
--- 6077,6111 ----
      case BUILT_IN_DWARF_SP_COLUMN:
        return expand_builtin_dwarf_sp_column ();
      case BUILT_IN_INIT_DWARF_REG_SIZES:
!       expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG0 (exp));
        return const0_rtx;
  #endif
      case BUILT_IN_FROB_RETURN_ADDR:
!       return expand_builtin_frob_return_addr (CALL_EXPR_ARG0 (exp));
      case BUILT_IN_EXTRACT_RETURN_ADDR:
!       return expand_builtin_extract_return_addr (CALL_EXPR_ARG0 (exp));
      case BUILT_IN_EH_RETURN:
!       expand_builtin_eh_return (CALL_EXPR_ARG0 (exp),
! 				CALL_EXPR_ARG1 (exp));
        return const0_rtx;
  #ifdef EH_RETURN_DATA_REGNO
      case BUILT_IN_EH_RETURN_DATA_REGNO:
!       return expand_builtin_eh_return_data_regno (exp);
  #endif
      case BUILT_IN_EXTEND_POINTER:
!       return expand_builtin_extend_pointer (CALL_EXPR_ARG0 (exp));
  
      case BUILT_IN_VA_START:
      case BUILT_IN_STDARG_START:
!       return expand_builtin_va_start (exp);
      case BUILT_IN_VA_END:
!       return expand_builtin_va_end (exp);
      case BUILT_IN_VA_COPY:
!       return expand_builtin_va_copy (exp);
      case BUILT_IN_EXPECT:
!       return expand_builtin_expect (exp, target);
      case BUILT_IN_PREFETCH:
!       expand_builtin_prefetch (exp);
        return const0_rtx;
  
      case BUILT_IN_PROFILE_FUNC_ENTER:
*************** expand_builtin (tree exp, rtx target, rt
*** 6137,6145 ****
        return expand_builtin_profile_func (true);
  
      case BUILT_IN_INIT_TRAMPOLINE:
!       return expand_builtin_init_trampoline (arglist);
      case BUILT_IN_ADJUST_TRAMPOLINE:
!       return expand_builtin_adjust_trampoline (arglist);
  
      case BUILT_IN_FORK:
      case BUILT_IN_EXECL:
--- 6114,6122 ----
        return expand_builtin_profile_func (true);
  
      case BUILT_IN_INIT_TRAMPOLINE:
!       return expand_builtin_init_trampoline (exp);
      case BUILT_IN_ADJUST_TRAMPOLINE:
!       return expand_builtin_adjust_trampoline (exp);
  
      case BUILT_IN_FORK:
      case BUILT_IN_EXECL:
*************** expand_builtin (tree exp, rtx target, rt
*** 6148,6154 ****
      case BUILT_IN_EXECLE:
      case BUILT_IN_EXECVP:
      case BUILT_IN_EXECVE:
!       target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
        if (target)
  	return target;
        break;
--- 6125,6131 ----
      case BUILT_IN_EXECLE:
      case BUILT_IN_EXECVP:
      case BUILT_IN_EXECVE:
!       target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6159,6165 ****
      case BUILT_IN_FETCH_AND_ADD_8:
      case BUILT_IN_FETCH_AND_ADD_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
!       target = expand_builtin_sync_operation (mode, arglist, PLUS,
  					      false, target, ignore);
        if (target)
  	return target;
--- 6136,6142 ----
      case BUILT_IN_FETCH_AND_ADD_8:
      case BUILT_IN_FETCH_AND_ADD_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
!       target = expand_builtin_sync_operation (mode, exp, PLUS,
  					      false, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6171,6177 ****
      case BUILT_IN_FETCH_AND_SUB_8:
      case BUILT_IN_FETCH_AND_SUB_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
!       target = expand_builtin_sync_operation (mode, arglist, MINUS,
  					      false, target, ignore);
        if (target)
  	return target;
--- 6148,6154 ----
      case BUILT_IN_FETCH_AND_SUB_8:
      case BUILT_IN_FETCH_AND_SUB_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
!       target = expand_builtin_sync_operation (mode, exp, MINUS,
  					      false, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6183,6189 ****
      case BUILT_IN_FETCH_AND_OR_8:
      case BUILT_IN_FETCH_AND_OR_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
!       target = expand_builtin_sync_operation (mode, arglist, IOR,
  					      false, target, ignore);
        if (target)
  	return target;
--- 6160,6166 ----
      case BUILT_IN_FETCH_AND_OR_8:
      case BUILT_IN_FETCH_AND_OR_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
!       target = expand_builtin_sync_operation (mode, exp, IOR,
  					      false, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6195,6201 ****
      case BUILT_IN_FETCH_AND_AND_8:
      case BUILT_IN_FETCH_AND_AND_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
!       target = expand_builtin_sync_operation (mode, arglist, AND,
  					      false, target, ignore);
        if (target)
  	return target;
--- 6172,6178 ----
      case BUILT_IN_FETCH_AND_AND_8:
      case BUILT_IN_FETCH_AND_AND_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
!       target = expand_builtin_sync_operation (mode, exp, AND,
  					      false, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6207,6213 ****
      case BUILT_IN_FETCH_AND_XOR_8:
      case BUILT_IN_FETCH_AND_XOR_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
!       target = expand_builtin_sync_operation (mode, arglist, XOR,
  					      false, target, ignore);
        if (target)
  	return target;
--- 6184,6190 ----
      case BUILT_IN_FETCH_AND_XOR_8:
      case BUILT_IN_FETCH_AND_XOR_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
!       target = expand_builtin_sync_operation (mode, exp, XOR,
  					      false, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6219,6225 ****
      case BUILT_IN_FETCH_AND_NAND_8:
      case BUILT_IN_FETCH_AND_NAND_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
!       target = expand_builtin_sync_operation (mode, arglist, NOT,
  					      false, target, ignore);
        if (target)
  	return target;
--- 6196,6202 ----
      case BUILT_IN_FETCH_AND_NAND_8:
      case BUILT_IN_FETCH_AND_NAND_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
!       target = expand_builtin_sync_operation (mode, exp, NOT,
  					      false, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6231,6237 ****
      case BUILT_IN_ADD_AND_FETCH_8:
      case BUILT_IN_ADD_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, arglist, PLUS,
  					      true, target, ignore);
        if (target)
  	return target;
--- 6208,6214 ----
      case BUILT_IN_ADD_AND_FETCH_8:
      case BUILT_IN_ADD_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, exp, PLUS,
  					      true, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6243,6249 ****
      case BUILT_IN_SUB_AND_FETCH_8:
      case BUILT_IN_SUB_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, arglist, MINUS,
  					      true, target, ignore);
        if (target)
  	return target;
--- 6220,6226 ----
      case BUILT_IN_SUB_AND_FETCH_8:
      case BUILT_IN_SUB_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, exp, MINUS,
  					      true, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6255,6261 ****
      case BUILT_IN_OR_AND_FETCH_8:
      case BUILT_IN_OR_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, arglist, IOR,
  					      true, target, ignore);
        if (target)
  	return target;
--- 6232,6238 ----
      case BUILT_IN_OR_AND_FETCH_8:
      case BUILT_IN_OR_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, exp, IOR,
  					      true, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6267,6273 ****
      case BUILT_IN_AND_AND_FETCH_8:
      case BUILT_IN_AND_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, arglist, AND,
  					      true, target, ignore);
        if (target)
  	return target;
--- 6244,6250 ----
      case BUILT_IN_AND_AND_FETCH_8:
      case BUILT_IN_AND_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, exp, AND,
  					      true, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6279,6285 ****
      case BUILT_IN_XOR_AND_FETCH_8:
      case BUILT_IN_XOR_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, arglist, XOR,
  					      true, target, ignore);
        if (target)
  	return target;
--- 6256,6262 ----
      case BUILT_IN_XOR_AND_FETCH_8:
      case BUILT_IN_XOR_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, exp, XOR,
  					      true, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6291,6297 ****
      case BUILT_IN_NAND_AND_FETCH_8:
      case BUILT_IN_NAND_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, arglist, NOT,
  					      true, target, ignore);
        if (target)
  	return target;
--- 6268,6274 ----
      case BUILT_IN_NAND_AND_FETCH_8:
      case BUILT_IN_NAND_AND_FETCH_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
!       target = expand_builtin_sync_operation (mode, exp, NOT,
  					      true, target, ignore);
        if (target)
  	return target;
*************** expand_builtin (tree exp, rtx target, rt
*** 6308,6314 ****
  	target = gen_reg_rtx (mode);
  
        mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
!       target = expand_builtin_compare_and_swap (mode, arglist, true, target);
        if (target)
  	return target;
        break;
--- 6285,6291 ----
  	target = gen_reg_rtx (mode);
  
        mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
!       target = expand_builtin_compare_and_swap (mode, exp, true, target);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6319,6325 ****
      case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
      case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
!       target = expand_builtin_compare_and_swap (mode, arglist, false, target);
        if (target)
  	return target;
        break;
--- 6296,6302 ----
      case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
      case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
!       target = expand_builtin_compare_and_swap (mode, exp, false, target);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6330,6336 ****
      case BUILT_IN_LOCK_TEST_AND_SET_8:
      case BUILT_IN_LOCK_TEST_AND_SET_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
!       target = expand_builtin_lock_test_and_set (mode, arglist, target);
        if (target)
  	return target;
        break;
--- 6307,6313 ----
      case BUILT_IN_LOCK_TEST_AND_SET_8:
      case BUILT_IN_LOCK_TEST_AND_SET_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
!       target = expand_builtin_lock_test_and_set (mode, exp, target);
        if (target)
  	return target;
        break;
*************** expand_builtin (tree exp, rtx target, rt
*** 6341,6347 ****
      case BUILT_IN_LOCK_RELEASE_8:
      case BUILT_IN_LOCK_RELEASE_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
!       expand_builtin_lock_release (mode, arglist);
        return const0_rtx;
  
      case BUILT_IN_SYNCHRONIZE:
--- 6318,6324 ----
      case BUILT_IN_LOCK_RELEASE_8:
      case BUILT_IN_LOCK_RELEASE_16:
        mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
!       expand_builtin_lock_release (mode, exp);
        return const0_rtx;
  
      case BUILT_IN_SYNCHRONIZE:
*************** expand_builtin (tree exp, rtx target, rt
*** 6392,6402 ****
  enum built_in_function
  builtin_mathfn_code (tree t)
  {
!   tree fndecl, arglist, parmlist;
    tree argtype, parmtype;
  
    if (TREE_CODE (t) != CALL_EXPR
!       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
      return END_BUILTINS;
  
    fndecl = get_callee_fndecl (t);
--- 6369,6380 ----
  enum built_in_function
  builtin_mathfn_code (tree t)
  {
!   tree fndecl, arg, parmlist;
    tree argtype, parmtype;
+   call_expr_arg_iterator iter;
  
    if (TREE_CODE (t) != CALL_EXPR
!       || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
      return END_BUILTINS;
  
    fndecl = get_callee_fndecl (t);
*************** builtin_mathfn_code (tree t)
*** 6406,6413 ****
        || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
      return END_BUILTINS;
  
-   arglist = TREE_OPERAND (t, 1);
    parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
    for (; parmlist; parmlist = TREE_CHAIN (parmlist))
      {
        /* If a function doesn't take a variable number of arguments,
--- 6384,6391 ----
        || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
      return END_BUILTINS;
  
    parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+   init_call_expr_arg_iterator (t, &iter);
    for (; parmlist; parmlist = TREE_CHAIN (parmlist))
      {
        /* If a function doesn't take a variable number of arguments,
*************** builtin_mathfn_code (tree t)
*** 6415,6429 ****
        parmtype = TREE_VALUE (parmlist);
        if (VOID_TYPE_P (parmtype))
  	{
! 	  if (arglist)
  	    return END_BUILTINS;
  	  return DECL_FUNCTION_CODE (fndecl);
  	}
  
!       if (! arglist)
  	return END_BUILTINS;
! 
!       argtype = TREE_TYPE (TREE_VALUE (arglist));
  
        if (SCALAR_FLOAT_TYPE_P (parmtype))
  	{
--- 6393,6408 ----
        parmtype = TREE_VALUE (parmlist);
        if (VOID_TYPE_P (parmtype))
  	{
! 	  if (more_call_expr_args_p (&iter))
  	    return END_BUILTINS;
  	  return DECL_FUNCTION_CODE (fndecl);
  	}
  
!       if (! more_call_expr_args_p (&iter))
  	return END_BUILTINS;
!       
!       arg = next_call_expr_arg (&iter);
!       argtype = TREE_TYPE (arg);
  
        if (SCALAR_FLOAT_TYPE_P (parmtype))
  	{
*************** builtin_mathfn_code (tree t)
*** 6447,6484 ****
  	}
        else
  	return END_BUILTINS;
- 
-       arglist = TREE_CHAIN (arglist);
      }
  
    /* Variable-length argument list.  */
    return DECL_FUNCTION_CODE (fndecl);
  }
  
! /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
!    constant.  ARGLIST is the argument list of the call.  */
  
  static tree
! fold_builtin_constant_p (tree arglist)
  {
-   if (arglist == 0)
-     return 0;
- 
-   arglist = TREE_VALUE (arglist);
- 
    /* We return 1 for a numeric type that's known to be a constant
       value at compile-time or for an aggregate type that's a
       literal constant.  */
!   STRIP_NOPS (arglist);
  
    /* If we know this is a constant, emit the constant of one.  */
!   if (CONSTANT_CLASS_P (arglist)
!       || (TREE_CODE (arglist) == CONSTRUCTOR
! 	  && TREE_CONSTANT (arglist)))
      return integer_one_node;
!   if (TREE_CODE (arglist) == ADDR_EXPR)
      {
!        tree op = TREE_OPERAND (arglist, 0);
         if (TREE_CODE (op) == STRING_CST
  	   || (TREE_CODE (op) == ARRAY_REF
  	       && integer_zerop (TREE_OPERAND (op, 1))
--- 6426,6456 ----
  	}
        else
  	return END_BUILTINS;
      }
  
    /* Variable-length argument list.  */
    return DECL_FUNCTION_CODE (fndecl);
  }
  
! /* Fold a call to __builtin_constant_p, if we know it ARG will evaluate to a
!    constant.  */
  
  static tree
! fold_builtin_constant_p (tree arg)
  {
    /* We return 1 for a numeric type that's known to be a constant
       value at compile-time or for an aggregate type that's a
       literal constant.  */
!   STRIP_NOPS (arg);
  
    /* If we know this is a constant, emit the constant of one.  */
!   if (CONSTANT_CLASS_P (arg)
!       || (TREE_CODE (arg) == CONSTRUCTOR
! 	  && TREE_CONSTANT (arg)))
      return integer_one_node;
!   if (TREE_CODE (arg) == ADDR_EXPR)
      {
!        tree op = TREE_OPERAND (arg, 0);
         if (TREE_CODE (op) == STRING_CST
  	   || (TREE_CODE (op) == ARRAY_REF
  	       && integer_zerop (TREE_OPERAND (op, 1))
*************** fold_builtin_constant_p (tree arglist)
*** 6493,6521 ****
       And finally, if we are compiling an initializer, not code, we
       need to return a definite result now; there's not going to be any
       more optimization done.  */
!   if (TREE_SIDE_EFFECTS (arglist)
!       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
!       || POINTER_TYPE_P (TREE_TYPE (arglist))
        || cfun == 0)
      return integer_zero_node;
  
    return 0;
  }
  
! /* Fold a call to __builtin_expect, if we expect that a comparison against
     the argument will fold to a constant.  In practice, this means a true
!    constant or the address of a non-weak symbol.  ARGLIST is the argument
!    list of the call.  */
  
  static tree
! fold_builtin_expect (tree arglist)
  {
!   tree arg, inner;
! 
!   if (arglist == 0)
!     return 0;
! 
!   arg = TREE_VALUE (arglist);
  
    /* If the argument isn't invariant, then there's nothing we can do.  */
    if (!TREE_INVARIANT (arg))
--- 6465,6487 ----
       And finally, if we are compiling an initializer, not code, we
       need to return a definite result now; there's not going to be any
       more optimization done.  */
!   if (TREE_SIDE_EFFECTS (arg)
!       || AGGREGATE_TYPE_P (TREE_TYPE (arg))
!       || POINTER_TYPE_P (TREE_TYPE (arg))
        || cfun == 0)
      return integer_zero_node;
  
    return 0;
  }
  
! /* Fold a call EXP to __builtin_expect, if we expect that a comparison against
     the argument will fold to a constant.  In practice, this means a true
!    constant or the address of a non-weak symbol. */
  
  static tree
! fold_builtin_expect (tree arg)
  {
!   tree inner;
  
    /* If the argument isn't invariant, then there's nothing we can do.  */
    if (!TREE_INVARIANT (arg))
*************** fold_builtin_expect (tree arglist)
*** 6543,6567 ****
  /* Fold a call to __builtin_classify_type.  */
  
  static tree
! fold_builtin_classify_type (tree arglist)
  {
!   if (arglist == 0)
      return build_int_cst (NULL_TREE, no_type_class);
  
!   return build_int_cst (NULL_TREE,
! 			type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
  }
  
  /* Fold a call to __builtin_strlen.  */
  
  static tree
! fold_builtin_strlen (tree arglist)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
      return NULL_TREE;
    else
      {
!       tree len = c_strlen (TREE_VALUE (arglist), 0);
  
        if (len)
  	{
--- 6509,6532 ----
  /* Fold a call to __builtin_classify_type.  */
  
  static tree
! fold_builtin_classify_type (tree arg)
  {
!   if (arg == 0)
      return build_int_cst (NULL_TREE, no_type_class);
  
!   return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
  }
  
  /* Fold a call to __builtin_strlen.  */
  
  static tree
! fold_builtin_strlen (tree arg)
  {
!   if (!validate_arg (arg, POINTER_TYPE))
      return NULL_TREE;
    else
      {
!       tree len = c_strlen (arg, 0);
  
        if (len)
  	{
*************** fold_builtin_inf (tree type, int warn)
*** 6599,6612 ****
  /* Fold a call to __builtin_nan or __builtin_nans.  */
  
  static tree
! fold_builtin_nan (tree arglist, tree type, int quiet)
  {
    REAL_VALUE_TYPE real;
    const char *str;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
      return 0;
!   str = c_getstr (TREE_VALUE (arglist));
    if (!str)
      return 0;
  
--- 6564,6577 ----
  /* Fold a call to __builtin_nan or __builtin_nans.  */
  
  static tree
! fold_builtin_nan (tree arg, tree type, int quiet)
  {
    REAL_VALUE_TYPE real;
    const char *str;
  
!   if (!validate_arg (arg, POINTER_TYPE))
      return 0;
!   str = c_getstr (arg);
    if (!str)
      return 0;
  
*************** integer_valued_real_p (tree t)
*** 6692,6711 ****
    return false;
  }
  
! /* EXP is assumed to be builtin call where truncation can be propagated
     across (for instance floor((double)f) == (double)floorf (f).
     Do the transformation.  */
  
  static tree
! fold_trunc_transparent_mathfn (tree fndecl, tree arglist)
  {
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
-   tree arg;
  
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
-   arg = TREE_VALUE (arglist);
    /* Integer rounding functions are idempotent.  */
    if (fcode == builtin_mathfn_code (arg))
      return arg;
--- 6657,6674 ----
    return false;
  }
  
! /* FNDECL is assumed to be a builtin where truncation can be propagated
     across (for instance floor((double)f) == (double)floorf (f).
     Do the transformation.  */
  
  static tree
! fold_trunc_transparent_mathfn (tree fndecl, tree arg)
  {
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
  
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* Integer rounding functions are idempotent.  */
    if (fcode == builtin_mathfn_code (arg))
      return arg;
*************** fold_trunc_transparent_mathfn (tree fnde
*** 6724,6753 ****
  
        if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
  	  && (decl = mathfn_built_in (newtype, fcode)))
! 	{
! 	  arglist =
! 	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
! 	  return fold_convert (ftype,
! 			       build_function_call_expr (decl, arglist));
! 	}
      }
    return 0;
  }
  
! /* EXP is assumed to be builtin call which can narrow the FP type of
     the argument, for instance lround((double)f) -> lroundf (f).  */
  
  static tree
! fold_fixed_mathfn (tree fndecl, tree arglist)
  {
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
-   tree arg;
  
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
-   arg = TREE_VALUE (arglist);
- 
    /* If argument is already integer valued, and we don't need to worry
       about setting errno, there's no need to perform rounding.  */
    if (! flag_errno_math && integer_valued_real_p (arg))
--- 6687,6710 ----
  
        if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
  	  && (decl = mathfn_built_in (newtype, fcode)))
! 	return fold_convert (ftype,
! 			     build_call_expr (decl, 1,
! 					      fold_convert (newtype, arg0)));
      }
    return 0;
  }
  
! /* FNDECL is assumed to be builtin which can narrow the FP type of
     the argument, for instance lround((double)f) -> lroundf (f).  */
  
  static tree
! fold_fixed_mathfn (tree fndecl, tree arg)
  {
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
  
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* If argument is already integer valued, and we don't need to worry
       about setting errno, there's no need to perform rounding.  */
    if (! flag_errno_math && integer_valued_real_p (arg))
*************** fold_fixed_mathfn (tree fndecl, tree arg
*** 6762,6789 ****
  
        if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
  	  && (decl = mathfn_built_in (newtype, fcode)))
! 	{
! 	  arglist =
! 	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
! 	  return build_function_call_expr (decl, arglist);
! 	}
      }
    return 0;
  }
  
! /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
!    is the argument list and TYPE is the return type.  Return
!    NULL_TREE if no if no simplification can be made.  */
  
  static tree
! fold_builtin_cabs (tree arglist, tree type)
  {
-   tree arg;
- 
-   if (!arglist || TREE_CHAIN (arglist))
-     return NULL_TREE;
- 
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
        || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
      return NULL_TREE;
--- 6719,6735 ----
  
        if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
  	  && (decl = mathfn_built_in (newtype, fcode)))
! 	return build_call_expr (decl, 1, fold_convert (newtype, arg0));
      }
    return 0;
  }
  
! /* Fold call to builtin cabs, cabsf or cabsl with argument ARG.  TYPE is the
!    return type.  Return NULL_TREE if no if no simplification can be made.  */
  
  static tree
! fold_builtin_cabs (tree arg, tree type)
  {
    if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
        || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
      return NULL_TREE;
*************** fold_builtin_cabs (tree arglist, tree ty
*** 6825,6831 ****
  
        if (sqrtfn != NULL_TREE)
  	{
! 	  tree rpart, ipart, result, arglist;
  
  	  arg = builtin_save_expr (arg);
  
--- 6771,6777 ----
  
        if (sqrtfn != NULL_TREE)
  	{
! 	  tree rpart, ipart, result;
  
  	  arg = builtin_save_expr (arg);
  
*************** fold_builtin_cabs (tree arglist, tree ty
*** 6841,6848 ****
  				fold_build2 (MULT_EXPR, type,
  					     ipart, ipart));
  
! 	  arglist = build_tree_list (NULL_TREE, result);
! 	  return build_function_call_expr (sqrtfn, arglist);
  	}
      }
  
--- 6787,6793 ----
  				fold_build2 (MULT_EXPR, type,
  					     ipart, ipart));
  
! 	  return build_call_expr (sqrtfn, 1, result);
  	}
      }
  
*************** fold_builtin_cabs (tree arglist, tree ty
*** 6853,6865 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_sqrt (tree arglist, tree type)
  {
  
    enum built_in_function fcode;
-   tree arg = TREE_VALUE (arglist);
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize sqrt of constant value.  */
--- 6798,6809 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_sqrt (tree arg, tree type)
  {
  
    enum built_in_function fcode;
  
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* Optimize sqrt of constant value.  */
*************** fold_builtin_sqrt (tree arglist, tree ty
*** 6878,6889 ****
    fcode = builtin_mathfn_code (arg);
    if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
      {
!       tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
        arg = fold_build2 (MULT_EXPR, type,
! 			 TREE_VALUE (TREE_OPERAND (arg, 1)),
  			 build_real (type, dconsthalf));
!       arglist = build_tree_list (NULL_TREE, arg);
!       return build_function_call_expr (expfn, arglist);
      }
  
    /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)).  */
--- 6822,6832 ----
    fcode = builtin_mathfn_code (arg);
    if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
      {
!       tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
        arg = fold_build2 (MULT_EXPR, type,
! 			 CALL_EXPR_ARG0 (arg),
  			 build_real (type, dconsthalf));
!       return build_call_expr (expfn, 1, arg);
      }
  
    /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)).  */
*************** fold_builtin_sqrt (tree arglist, tree ty
*** 6893,6899 ****
  
        if (powfn)
  	{
! 	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
  	  tree tree_root;
  	  /* The inner root was either sqrt or cbrt.  */
  	  REAL_VALUE_TYPE dconstroot =
--- 6836,6842 ----
  
        if (powfn)
  	{
! 	  tree arg0 = CALL_EXPR_ARG0 (arg);
  	  tree tree_root;
  	  /* The inner root was either sqrt or cbrt.  */
  	  REAL_VALUE_TYPE dconstroot =
*************** fold_builtin_sqrt (tree arglist, tree ty
*** 6903,6911 ****
  	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
  	  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
  	  tree_root = build_real (type, dconstroot);
! 	  arglist = tree_cons (NULL_TREE, arg0,
! 			       build_tree_list (NULL_TREE, tree_root));
! 	  return build_function_call_expr (powfn, arglist);
  	}
      }
  
--- 6846,6852 ----
  	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
  	  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
  	  tree_root = build_real (type, dconstroot);
! 	  return build_call_expr (powfn, 2, arg0, tree_root);
  	}
      }
  
*************** fold_builtin_sqrt (tree arglist, tree ty
*** 6915,6931 ****
  	  || fcode == BUILT_IN_POWF
  	  || fcode == BUILT_IN_POWL))
      {
!       tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
!       tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
!       tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
        tree narg1;
        if (!tree_expr_nonnegative_p (arg0))
  	arg0 = build1 (ABS_EXPR, type, arg0);
        narg1 = fold_build2 (MULT_EXPR, type, arg1,
  			   build_real (type, dconsthalf));
!       arglist = tree_cons (NULL_TREE, arg0,
! 			   build_tree_list (NULL_TREE, narg1));
!       return build_function_call_expr (powfn, arglist);
      }
  
    return NULL_TREE;
--- 6856,6870 ----
  	  || fcode == BUILT_IN_POWF
  	  || fcode == BUILT_IN_POWL))
      {
!       tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
!       tree arg0 = CALL_EXPR_ARG0 (arg);
!       tree arg1 = CALL_EXPR_ARG1 (arg);
        tree narg1;
        if (!tree_expr_nonnegative_p (arg0))
  	arg0 = build1 (ABS_EXPR, type, arg0);
        narg1 = fold_build2 (MULT_EXPR, type, arg1,
  			   build_real (type, dconsthalf));
!       return build_call_expr (powfn, 2, arg0, narg1);
      }
  
    return NULL_TREE;
*************** fold_builtin_sqrt (tree arglist, tree ty
*** 6934,6945 ****
  /* Fold a builtin function call to cbrt, cbrtf, or cbrtl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_cbrt (tree arglist, tree type)
  {
-   tree arg = TREE_VALUE (arglist);
    const enum built_in_function fcode = builtin_mathfn_code (arg);
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize cbrt of constant value.  */
--- 6873,6883 ----
  /* Fold a builtin function call to cbrt, cbrtf, or cbrtl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_cbrt (tree arg, tree type)
  {
    const enum built_in_function fcode = builtin_mathfn_code (arg);
  
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* Optimize cbrt of constant value.  */
*************** fold_builtin_cbrt (tree arglist, tree ty
*** 6951,6964 ****
        /* Optimize cbrt(expN(x)) -> expN(x/3).  */
        if (BUILTIN_EXPONENT_P (fcode))
  	{
! 	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
  	  const REAL_VALUE_TYPE third_trunc =
  	    real_value_truncate (TYPE_MODE (type), dconstthird);
  	  arg = fold_build2 (MULT_EXPR, type,
  			     TREE_VALUE (TREE_OPERAND (arg, 1)),
  			     build_real (type, third_trunc));
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  return build_function_call_expr (expfn, arglist);
  	}
  
        /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
--- 6889,6901 ----
        /* Optimize cbrt(expN(x)) -> expN(x/3).  */
        if (BUILTIN_EXPONENT_P (fcode))
  	{
! 	  tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
  	  const REAL_VALUE_TYPE third_trunc =
  	    real_value_truncate (TYPE_MODE (type), dconstthird);
  	  arg = fold_build2 (MULT_EXPR, type,
  			     TREE_VALUE (TREE_OPERAND (arg, 1)),
  			     build_real (type, third_trunc));
! 	  return build_call_expr (expfn, 1, arg);
  	}
  
        /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
*************** fold_builtin_cbrt (tree arglist, tree ty
*** 6968,6990 ****
  
  	  if (powfn)
  	    {
! 	      tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
  	      tree tree_root;
  	      REAL_VALUE_TYPE dconstroot = dconstthird;
  
  	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
  	      dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
  	      tree_root = build_real (type, dconstroot);
! 	      arglist = tree_cons (NULL_TREE, arg0,
! 				   build_tree_list (NULL_TREE, tree_root));
! 	      return build_function_call_expr (powfn, arglist);
  	    }
  	}
  
        /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
        if (BUILTIN_CBRT_P (fcode))
  	{
! 	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
  	  if (tree_expr_nonnegative_p (arg0))
  	    {
  	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
--- 6905,6925 ----
  
  	  if (powfn)
  	    {
! 	      tree arg0 = CALL_EXPR_ARG0 (arg);
  	      tree tree_root;
  	      REAL_VALUE_TYPE dconstroot = dconstthird;
  
  	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
  	      dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
  	      tree_root = build_real (type, dconstroot);
! 	      return build_call_expr (powfn, 2, arg0, tree_root);
  	    }
  	}
  
        /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
        if (BUILTIN_CBRT_P (fcode))
  	{
! 	  tree arg0 = CALL_EXPR_ARG0 (arg);
  	  if (tree_expr_nonnegative_p (arg0))
  	    {
  	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
*************** fold_builtin_cbrt (tree arglist, tree ty
*** 6997,7005 ****
  		  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
  		  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
  		  tree_root = build_real (type, dconstroot);
! 		  arglist = tree_cons (NULL_TREE, arg0,
! 				       build_tree_list (NULL_TREE, tree_root));
! 		  return build_function_call_expr (powfn, arglist);
  		}
  	    }
  	}
--- 6932,6938 ----
  		  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
  		  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
  		  tree_root = build_real (type, dconstroot);
! 		  return build_call_expr (powfn, 2, arg0, tree_root);
  		}
  	    }
  	}
*************** fold_builtin_cbrt (tree arglist, tree ty
*** 7008,7025 ****
        if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
  	  || fcode == BUILT_IN_POWL)
  	{
! 	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
! 	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
  	  if (tree_expr_nonnegative_p (arg00))
  	    {
! 	      tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
  	      const REAL_VALUE_TYPE dconstroot
  		= real_value_truncate (TYPE_MODE (type), dconstthird);
  	      tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
  					 build_real (type, dconstroot));
! 	      arglist = tree_cons (NULL_TREE, arg00,
! 				   build_tree_list (NULL_TREE, narg01));
! 	      return build_function_call_expr (powfn, arglist);
  	    }
  	}
      }
--- 6941,6956 ----
        if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
  	  || fcode == BUILT_IN_POWL)
  	{
! 	  tree arg00 = CALL_EXPR_ARG0 (arg);
! 	  tree arg01 = CALL_EXPR_ARG1 (arg);
  	  if (tree_expr_nonnegative_p (arg00))
  	    {
! 	      tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
  	      const REAL_VALUE_TYPE dconstroot
  		= real_value_truncate (TYPE_MODE (type), dconstthird);
  	      tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
  					 build_real (type, dconstroot));
! 	      return build_call_expr (powfn, 2, arg00, narg01);
  	    }
  	}
      }
*************** fold_builtin_cbrt (tree arglist, tree ty
*** 7029,7039 ****
  /* Fold function call to builtin sin, sinf, or sinl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_sin (tree arglist)
  {
!   tree arg = TREE_VALUE (arglist);
! 
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize sin (0.0) = 0.0.  */
--- 6960,6968 ----
  /* Fold function call to builtin sin, sinf, or sinl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_sin (tree arg)
  {
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* Optimize sin (0.0) = 0.0.  */
*************** fold_builtin_sin (tree arglist)
*** 7046,7056 ****
  /* Fold function call to builtin cos, cosf, or cosl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_cos (tree arglist, tree type, tree fndecl)
  {
!   tree arg = TREE_VALUE (arglist);
! 
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize cos (0.0) = 1.0.  */
--- 6975,6983 ----
  /* Fold function call to builtin cos, cosf, or cosl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_cos (tree arg, tree type, tree fndecl)
  {
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* Optimize cos (0.0) = 1.0.  */
*************** fold_builtin_cos (tree arglist, tree typ
*** 7059,7069 ****
  
    /* Optimize cos(-x) into cos (x).  */
    if (TREE_CODE (arg) == NEGATE_EXPR)
!     {
!       tree args = build_tree_list (NULL_TREE,
! 				   TREE_OPERAND (arg, 0));
!       return build_function_call_expr (fndecl, args);
!     }
  
    return NULL_TREE;
  }
--- 6986,6992 ----
  
    /* Optimize cos(-x) into cos (x).  */
    if (TREE_CODE (arg) == NEGATE_EXPR)
!     return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0));
  
    return NULL_TREE;
  }
*************** fold_builtin_cos (tree arglist, tree typ
*** 7071,7082 ****
  /* Fold function call to builtin tan, tanf, or tanl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_tan (tree arglist)
  {
    enum built_in_function fcode;
-   tree arg = TREE_VALUE (arglist);
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize tan(0.0) = 0.0.  */
--- 6994,7004 ----
  /* Fold function call to builtin tan, tanf, or tanl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_tan (tree arg)
  {
    enum built_in_function fcode;
  
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* Optimize tan(0.0) = 0.0.  */
*************** fold_builtin_tan (tree arglist)
*** 7089,7095 ****
        && (fcode == BUILT_IN_ATAN
  	  || fcode == BUILT_IN_ATANF
  	  || fcode == BUILT_IN_ATANL))
!     return TREE_VALUE (TREE_OPERAND (arg, 1));
  
    return NULL_TREE;
  }
--- 7011,7017 ----
        && (fcode == BUILT_IN_ATAN
  	  || fcode == BUILT_IN_ATANF
  	  || fcode == BUILT_IN_ATANL))
!     return CALL_EXPR_ARG0 (arg);
  
    return NULL_TREE;
  }
*************** fold_builtin_tan (tree arglist)
*** 7098,7109 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_atan (tree arglist, tree type)
  {
! 
!   tree arg = TREE_VALUE (arglist);
! 
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize atan(0.0) = 0.0.  */
--- 7020,7028 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_atan (tree arg, tree type)
  {
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* Optimize atan(0.0) = 0.0.  */
*************** fold_builtin_atan (tree arglist, tree ty
*** 7127,7141 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_trunc (tree fndecl, tree arglist)
  {
!   tree arg;
! 
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
    /* Optimize trunc of constant value.  */
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE r, x;
--- 7046,7057 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_trunc (tree fndecl, tree arg)
  {
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* Optimize trunc of constant value.  */
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE r, x;
*************** fold_builtin_trunc (tree fndecl, tree ar
*** 7146,7167 ****
        return build_real (type, r);
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arglist);
  }
  
  /* Fold function call to builtin floor, floorf or floorl.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_floor (tree fndecl, tree arglist)
  {
!   tree arg;
! 
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
    /* Optimize floor of constant value.  */
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE x;
--- 7062,7080 ----
        return build_real (type, r);
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arg);
  }
  
  /* Fold function call to builtin floor, floorf or floorl.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_floor (tree fndecl, tree arg)
  {
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* Optimize floor of constant value.  */
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE x;
*************** fold_builtin_floor (tree fndecl, tree ar
*** 7177,7198 ****
  	}
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arglist);
  }
  
  /* Fold function call to builtin ceil, ceilf or ceill.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_ceil (tree fndecl, tree arglist)
  {
!   tree arg;
! 
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
    /* Optimize ceil of constant value.  */
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE x;
--- 7090,7108 ----
  	}
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arg);
  }
  
  /* Fold function call to builtin ceil, ceilf or ceill.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_ceil (tree fndecl, tree arg)
  {
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* Optimize ceil of constant value.  */
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE x;
*************** fold_builtin_ceil (tree fndecl, tree arg
*** 7208,7229 ****
  	}
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arglist);
  }
  
  /* Fold function call to builtin round, roundf or roundl.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_round (tree fndecl, tree arglist)
  {
!   tree arg;
! 
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
    /* Optimize round of constant value.  */
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE x;
--- 7118,7136 ----
  	}
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arg);
  }
  
  /* Fold function call to builtin round, roundf or roundl.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_round (tree fndecl, tree arg)
  {
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* Optimize round of constant value.  */
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        REAL_VALUE_TYPE x;
*************** fold_builtin_round (tree fndecl, tree ar
*** 7239,7245 ****
  	}
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arglist);
  }
  
  /* Fold function call to builtin lround, lroundf or lroundl (or the
--- 7146,7152 ----
  	}
      }
  
!   return fold_trunc_transparent_mathfn (fndecl, arg);
  }
  
  /* Fold function call to builtin lround, lroundf or lroundl (or the
*************** fold_builtin_round (tree fndecl, tree ar
*** 7247,7261 ****
     Return NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_int_roundingfn (tree fndecl, tree arglist)
  {
!   tree arg;
! 
!   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
    /* Optimize lround of constant value.  */
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
--- 7154,7165 ----
     Return NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_int_roundingfn (tree fndecl, tree arg)
  {
!   if (! validate_arg (arg, REAL_TYPE))
      return 0;
  
    /* Optimize lround of constant value.  */
    if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
*************** fold_builtin_int_roundingfn (tree fndecl
*** 7295,7301 ****
  	}
      }
  
!   return fold_fixed_mathfn (fndecl, arglist);
  }
  
  /* Fold function call to builtin ffs, clz, ctz, popcount and parity
--- 7199,7205 ----
  	}
      }
  
!   return fold_fixed_mathfn (fndecl, arg);
  }
  
  /* Fold function call to builtin ffs, clz, ctz, popcount and parity
*************** fold_builtin_int_roundingfn (tree fndecl
*** 7303,7317 ****
     Return NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_bitop (tree fndecl, tree arglist)
  {
!   tree arg;
! 
!   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize for constant argument.  */
-   arg = TREE_VALUE (arglist);
    if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        HOST_WIDE_INT hi, width, result;
--- 7207,7218 ----
     Return NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_bitop (tree fndecl, tree arg)
  {
!   if (! validate_arg (arg, INTEGER_TYPE))
      return NULL_TREE;
  
    /* Optimize for constant argument.  */
    if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
      {
        HOST_WIDE_INT hi, width, result;
*************** real_dconstp (tree expr, const REAL_VALU
*** 7408,7424 ****
  }
  
  /* A subroutine of fold_builtin to fold the various logarithmic
!    functions.  EXP is the CALL_EXPR of a call to a builtin logN
     function.  VALUE is the base of the logN function.  */
  
  static tree
! fold_builtin_logarithm (tree fndecl, tree arglist,
  			const REAL_VALUE_TYPE *value)
  {
!   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      {
        tree type = TREE_TYPE (TREE_TYPE (fndecl));
-       tree arg = TREE_VALUE (arglist);
        const enum built_in_function fcode = builtin_mathfn_code (arg);
  
        /* Optimize logN(1.0) = 0.0.  */
--- 7309,7324 ----
  }
  
  /* A subroutine of fold_builtin to fold the various logarithmic
!    functions.  ARG is the argument of a call to a builtin logN
     function.  VALUE is the base of the logN function.  */
  
  static tree
! fold_builtin_logarithm (tree fndecl, tree arg,
  			const REAL_VALUE_TYPE *value)
  {
!   if (validate_arg (arg, REAL_TYPE))
      {
        tree type = TREE_TYPE (TREE_TYPE (fndecl));
        const enum built_in_function fcode = builtin_mathfn_code (arg);
  
        /* Optimize logN(1.0) = 0.0.  */
*************** fold_builtin_logarithm (tree fndecl, tre
*** 7447,7453 ****
  		      || fcode == BUILT_IN_EXP2F
  		      || fcode == BUILT_IN_EXP2L))
  	      || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
! 	return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
  
        /* Optimize logN(func()) for various exponential functions.  We
  	 want to determine the value "x" and the power "exponent" in
--- 7347,7353 ----
  		      || fcode == BUILT_IN_EXP2F
  		      || fcode == BUILT_IN_EXP2L))
  	      || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
! 	return fold_convert (type, CALL_EXPR_ARG0 (arg));
  
        /* Optimize logN(func()) for various exponential functions.  We
  	 want to determine the value "x" and the power "exponent" in
*************** fold_builtin_logarithm (tree fndecl, tre
*** 7462,7495 ****
  	    /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
  	    x = build_real (type,
  			    real_value_truncate (TYPE_MODE (type), dconste));
! 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
  	    break;
  	  CASE_FLT_FN (BUILT_IN_EXP2):
  	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
  	    x = build_real (type, dconst2);
! 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
  	    break;
  	  CASE_FLT_FN (BUILT_IN_EXP10):
  	  CASE_FLT_FN (BUILT_IN_POW10):
  	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
  	    x = build_real (type, dconst10);
! 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
  	    break;
  	  CASE_FLT_FN (BUILT_IN_SQRT):
  	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
! 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
  	    exponent = build_real (type, dconsthalf);
  	    break;
  	  CASE_FLT_FN (BUILT_IN_CBRT):
  	    /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
! 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
  	    exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
  							      dconstthird));
  	    break;
  	  CASE_FLT_FN (BUILT_IN_POW):
  	    /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
! 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
! 	    exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
  	    break;
  	  default:
  	    break;
--- 7362,7395 ----
  	    /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
  	    x = build_real (type,
  			    real_value_truncate (TYPE_MODE (type), dconste));
! 	    exponent = CALL_EXPR_ARG0 (arg);
  	    break;
  	  CASE_FLT_FN (BUILT_IN_EXP2):
  	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
  	    x = build_real (type, dconst2);
! 	    exponent = CALL_EXPR_ARG0 (arg);
  	    break;
  	  CASE_FLT_FN (BUILT_IN_EXP10):
  	  CASE_FLT_FN (BUILT_IN_POW10):
  	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
  	    x = build_real (type, dconst10);
! 	    exponent = CALL_EXPR_ARG0 (arg);
  	    break;
  	  CASE_FLT_FN (BUILT_IN_SQRT):
  	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
! 	    x = CALL_EXPR_ARG0 (arg);
  	    exponent = build_real (type, dconsthalf);
  	    break;
  	  CASE_FLT_FN (BUILT_IN_CBRT):
  	    /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
! 	    x = CALL_EXPR_ARG0 (arg);
  	    exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
  							      dconstthird));
  	    break;
  	  CASE_FLT_FN (BUILT_IN_POW):
  	    /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
! 	    x = CALL_EXPR_ARG0 (arg);
! 	    exponent = CALL_EXPR_ARG1 (arg);
  	    break;
  	  default:
  	    break;
*************** fold_builtin_logarithm (tree fndecl, tre
*** 7498,7506 ****
  	  /* Now perform the optimization.  */
  	  if (x && exponent)
  	    {
! 	      tree logfn;
! 	      arglist = build_tree_list (NULL_TREE, x);
! 	      logfn = build_function_call_expr (fndecl, arglist);
  	      return fold_build2 (MULT_EXPR, type, exponent, logfn);
  	    }
  	}
--- 7398,7404 ----
  	  /* Now perform the optimization.  */
  	  if (x && exponent)
  	    {
! 	      tree logfn = build_call_expr (fndecl, 1, x);
  	      return fold_build2 (MULT_EXPR, type, exponent, logfn);
  	    }
  	}
*************** fold_builtin_logarithm (tree fndecl, tre
*** 7512,7523 ****
  /* Fold a builtin function call to pow, powf, or powl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_pow (tree fndecl, tree arglist, tree type)
  {
!   tree arg0 = TREE_VALUE (arglist);
!   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
! 
!   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize pow(1.0,y) = 1.0.  */
--- 7410,7418 ----
  /* Fold a builtin function call to pow, powf, or powl.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
  {
!   if (! (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE)))
      return NULL_TREE;
  
    /* Optimize pow(1.0,y) = 1.0.  */
*************** fold_builtin_pow (tree fndecl, tree argl
*** 7554,7563 ****
  	  tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
  
  	  if (sqrtfn != NULL_TREE)
! 	    {
! 	      tree arglist = build_tree_list (NULL_TREE, arg0);
! 	      return build_function_call_expr (sqrtfn, arglist);
! 	    }
  	}
  
        /* Check for an integer exponent.  */
--- 7449,7455 ----
  	  tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
  
  	  if (sqrtfn != NULL_TREE)
! 	    return build_call_expr (sqrtfn, 1, arg0);
  	}
  
        /* Check for an integer exponent.  */
*************** fold_builtin_pow (tree fndecl, tree argl
*** 7583,7593 ****
  	    {
  	      tree narg0 = fold_strip_sign_ops (arg0);
  	      if (narg0)
! 		{
! 		  arglist = build_tree_list (NULL_TREE, arg1);
! 		  arglist = tree_cons (NULL_TREE, narg0, arglist);
! 		  return build_function_call_expr (fndecl, arglist);
! 		}
  	    }
  	}
      }
--- 7475,7481 ----
  	    {
  	      tree narg0 = fold_strip_sign_ops (arg0);
  	      if (narg0)
! 		return build_call_expr (fndecl, 2, narg0, arg1);
  	    }
  	}
      }
*************** fold_builtin_pow (tree fndecl, tree argl
*** 7599,7636 ****
        /* Optimize pow(expN(x),y) = expN(x*y).  */
        if (BUILTIN_EXPONENT_P (fcode))
  	{
! 	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
! 	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
  	  arg = fold_build2 (MULT_EXPR, type, arg, arg1);
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  return build_function_call_expr (expfn, arglist);
  	}
  
        /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
        if (BUILTIN_SQRT_P (fcode))
  	{
! 	  tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
  	  tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
  				    build_real (type, dconsthalf));
! 
! 	  arglist = tree_cons (NULL_TREE, narg0,
! 			       build_tree_list (NULL_TREE, narg1));
! 	  return build_function_call_expr (fndecl, arglist);
  	}
  
        /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
        if (BUILTIN_CBRT_P (fcode))
  	{
! 	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
  	  if (tree_expr_nonnegative_p (arg))
  	    {
  	      const REAL_VALUE_TYPE dconstroot
  		= real_value_truncate (TYPE_MODE (type), dconstthird);
  	      tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
  					build_real (type, dconstroot));
! 	      arglist = tree_cons (NULL_TREE, arg,
! 				   build_tree_list (NULL_TREE, narg1));
! 	      return build_function_call_expr (fndecl, arglist);
  	    }
  	}
  
--- 7487,7518 ----
        /* Optimize pow(expN(x),y) = expN(x*y).  */
        if (BUILTIN_EXPONENT_P (fcode))
  	{
! 	  tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
! 	  tree arg = CALL_EXPR_ARG0 (arg0);
  	  arg = fold_build2 (MULT_EXPR, type, arg, arg1);
! 	  return build_call_expr (expfn, 1, arg);
  	}
  
        /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
        if (BUILTIN_SQRT_P (fcode))
  	{
! 	  tree narg0 = CALL_EXPR_ARG0 (arg0);
  	  tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
  				    build_real (type, dconsthalf));
! 	  return build_call_expr (fndecl, 2, narg0, narg1);
  	}
  
        /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
        if (BUILTIN_CBRT_P (fcode))
  	{
! 	  tree arg = CALL_EXPR_ARG0 (arg0);
  	  if (tree_expr_nonnegative_p (arg))
  	    {
  	      const REAL_VALUE_TYPE dconstroot
  		= real_value_truncate (TYPE_MODE (type), dconstthird);
  	      tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
  					build_real (type, dconstroot));
! 	      return build_call_expr (fndecl, 2, arg, narg1);
  	    }
  	}
  
*************** fold_builtin_pow (tree fndecl, tree argl
*** 7638,7649 ****
        if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
  	   || fcode == BUILT_IN_POWL)
  	{
! 	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
! 	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
  	  tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
! 	  arglist = tree_cons (NULL_TREE, arg00,
! 			       build_tree_list (NULL_TREE, narg1));
! 	  return build_function_call_expr (fndecl, arglist);
  	}
      }
  
--- 7520,7529 ----
        if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
  	   || fcode == BUILT_IN_POWL)
  	{
! 	  tree arg00 = CALL_EXPR_ARG0 (arg0);
! 	  tree arg01 = CALL_EXPR_ARG1 (arg0);
  	  tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
! 	  return build_call_expr (fndecl, 2, arg00, narg1);
  	}
      }
  
*************** fold_builtin_pow (tree fndecl, tree argl
*** 7653,7664 ****
  /* Fold a builtin function call to powi, powif, or powil.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
  {
!   tree arg0 = TREE_VALUE (arglist);
!   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
! 
!   if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
      return NULL_TREE;
  
    /* Optimize pow(1.0,y) = 1.0.  */
--- 7533,7542 ----
  /* Fold a builtin function call to powi, powif, or powil.  Return
     NULL_TREE if no simplification can be made.  */
  static tree
! fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED,
! 		   tree arg0, tree arg1, tree type)
  {
!   if (! (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE)))
      return NULL_TREE;
  
    /* Optimize pow(1.0,y) = 1.0.  */
*************** fold_builtin_powi (tree fndecl ATTRIBUTE
*** 7698,7714 ****
  }
  
  /* A subroutine of fold_builtin to fold the various exponent
!    functions.  EXP is the CALL_EXPR of a call to a builtin function.
     VALUE is the value which will be raised to a power.  */
  
  static tree
! fold_builtin_exponent (tree fndecl, tree arglist,
  		       const REAL_VALUE_TYPE *value)
  {
!   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      {
        tree type = TREE_TYPE (TREE_TYPE (fndecl));
-       tree arg = TREE_VALUE (arglist);
  
        /* Optimize exp*(0.0) = 1.0.  */
        if (real_zerop (arg))
--- 7576,7591 ----
  }
  
  /* A subroutine of fold_builtin to fold the various exponent
!    functions.  ARG is the argument of a call to a builtin function.
     VALUE is the value which will be raised to a power.  */
  
  static tree
! fold_builtin_exponent (tree fndecl, tree arg,
  		       const REAL_VALUE_TYPE *value)
  {
!   if (validate_arg (arg, REAL_TYPE))
      {
        tree type = TREE_TYPE (TREE_TYPE (fndecl));
  
        /* Optimize exp*(0.0) = 1.0.  */
        if (real_zerop (arg))
*************** fold_builtin_exponent (tree fndecl, tree
*** 7762,7768 ****
  		  && (fcode == BUILT_IN_LOG10
  		      || fcode == BUILT_IN_LOG10F
  		      || fcode == BUILT_IN_LOG10L)))
! 	    return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
  	}
      }
  
--- 7639,7645 ----
  		  && (fcode == BUILT_IN_LOG10
  		      || fcode == BUILT_IN_LOG10F
  		      || fcode == BUILT_IN_LOG10L)))
! 	    return fold_convert (type, CALL_EXPR_ARG0 (arg));
  	}
      }
  
*************** fold_builtin_exponent (tree fndecl, tree
*** 7773,7797 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_memcpy (tree fndecl, tree arglist)
  {
!   tree dest, src, len;
! 
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    /* If the LEN parameter is zero, return DEST.  */
    if (integer_zerop (len))
!     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
  
    /* If SRC and DEST are the same (and not volatile), return DEST.  */
    if (operand_equal_p (src, dest, 0))
!     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
  
    return 0;
  }
--- 7650,7669 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_memcpy (tree dest, tree src, tree len, tree type)
  {
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
      return 0;
  
    /* If the LEN parameter is zero, return DEST.  */
    if (integer_zerop (len))
!     return omit_one_operand (type, dest, src);
  
    /* If SRC and DEST are the same (and not volatile), return DEST.  */
    if (operand_equal_p (src, dest, 0))
!     return omit_one_operand (type, dest, len);
  
    return 0;
  }
*************** fold_builtin_memcpy (tree fndecl, tree a
*** 7800,7833 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_mempcpy (tree arglist, tree type, int endp)
  {
!   if (validate_arglist (arglist,
! 			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
!     {
!       tree dest = TREE_VALUE (arglist);
!       tree src = TREE_VALUE (TREE_CHAIN (arglist));
!       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
! 
!       /* If the LEN parameter is zero, return DEST.  */
!       if (integer_zerop (len))
! 	return omit_one_operand (type, dest, src);
  
!       /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
!       if (operand_equal_p (src, dest, 0))
! 	{
! 	  if (endp == 0)
! 	    return omit_one_operand (type, dest, len);
  
! 	  if (endp == 2)
! 	    len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
! 			       ssize_int (1));
  
! 	  len = fold_convert (TREE_TYPE (dest), len);
! 	  len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
! 	  return fold_convert (type, len);
! 	}
      }
    return 0;
  }
  
--- 7672,7703 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_mempcpy (tree dest, tree src, tree len, tree type, int endp)
  {
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
!     return 0;
  
!   /* If the LEN parameter is zero, return DEST.  */
!   if (integer_zerop (len))
!     return omit_one_operand (type, dest, src);
  
!   /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
!   if (operand_equal_p (src, dest, 0))
!     {
!       if (endp == 0)
! 	return omit_one_operand (type, dest, len);
  
!       if (endp == 2)
! 	len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
! 			   ssize_int (1));
! 
!       len = fold_convert (TREE_TYPE (dest), len);
!       len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
!       return fold_convert (type, len);
      }
+ 
    return 0;
  }
  
*************** fold_builtin_mempcpy (tree arglist, tree
*** 7835,7852 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_memmove (tree arglist, tree type)
  {
-   tree dest, src, len;
  
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    /* If the LEN parameter is zero, return DEST.  */
    if (integer_zerop (len))
      return omit_one_operand (type, dest, src);
--- 7705,7718 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_memmove (tree dest, tree src, tree len, tree type)
  {
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
      return 0;
  
    /* If the LEN parameter is zero, return DEST.  */
    if (integer_zerop (len))
      return omit_one_operand (type, dest, src);
*************** fold_builtin_memmove (tree arglist, tree
*** 7863,7879 ****
     simplification can be made.  */
  
  tree
! fold_builtin_strcpy (tree fndecl, tree arglist, tree len)
  {
!   tree dest, src, fn;
  
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
- 
    /* If SRC and DEST are the same (and not volatile), return DEST.  */
    if (operand_equal_p (src, dest, 0))
      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
--- 7729,7742 ----
     simplification can be made.  */
  
  tree
! fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len)
  {
!   tree fn;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)))
      return 0;
  
    /* If SRC and DEST are the same (and not volatile), return DEST.  */
    if (operand_equal_p (src, dest, 0))
      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
*************** fold_builtin_strcpy (tree fndecl, tree a
*** 7893,7903 ****
      }
  
    len = size_binop (PLUS_EXPR, len, ssize_int (1));
-   arglist = build_tree_list (NULL_TREE, len);
-   arglist = tree_cons (NULL_TREE, src, arglist);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
! 		       build_function_call_expr (fn, arglist));
  }
  
  /* Fold function call to builtin strncpy.  If SLEN is not NULL, it represents
--- 7756,7763 ----
      }
  
    len = size_binop (PLUS_EXPR, len, ssize_int (1));
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
! 		       build_call_expr (fn, 3, dest, src, len));
  }
  
  /* Fold function call to builtin strncpy.  If SLEN is not NULL, it represents
*************** fold_builtin_strcpy (tree fndecl, tree a
*** 7905,7922 ****
     can be made.  */
  
  tree
! fold_builtin_strncpy (tree fndecl, tree arglist, tree slen)
  {
!   tree dest, src, len, fn;
  
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    /* If the LEN parameter is zero, return DEST.  */
    if (integer_zerop (len))
      return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
--- 7765,7779 ----
     can be made.  */
  
  tree
! fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen)
  {
!   tree fn;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
      return 0;
  
    /* If the LEN parameter is zero, return DEST.  */
    if (integer_zerop (len))
      return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
*************** fold_builtin_strncpy (tree fndecl, tree 
*** 7946,7971 ****
    if (!fn)
      return 0;
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
! 		       build_function_call_expr (fn, arglist));
  }
  
  /* Fold function call to builtin memcmp.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_memcmp (tree arglist)
  {
-   tree arg1, arg2, len;
    const char *p1, *p2;
  
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   arg1 = TREE_VALUE (arglist);
-   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    /* If the LEN parameter is zero, return zero.  */
    if (integer_zerop (len))
      return omit_two_operands (integer_type_node, integer_zero_node,
--- 7803,7824 ----
    if (!fn)
      return 0;
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
! 		       build_call_expr (fn, 3, dest, src, len));
  }
  
  /* Fold function call to builtin memcmp.  Return
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_memcmp (tree arg1, tree arg2, tree len)
  {
    const char *p1, *p2;
  
!   if (! (validate_arg (arg1, POINTER_TYPE)
! 	 && validate_arg (arg2, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
      return 0;
  
    /* If the LEN parameter is zero, return zero.  */
    if (integer_zerop (len))
      return omit_two_operands (integer_type_node, integer_zero_node,
*************** fold_builtin_memcmp (tree arglist)
*** 8020,8036 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_strcmp (tree arglist)
  {
-   tree arg1, arg2;
    const char *p1, *p2;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
  
-   arg1 = TREE_VALUE (arglist);
-   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
- 
    /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
    if (operand_equal_p (arg1, arg2, 0))
      return integer_zero_node;
--- 7873,7886 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_strcmp (tree arg1, tree arg2)
  {
    const char *p1, *p2;
  
!   if (! (validate_arg (arg1, POINTER_TYPE)
! 	 && validate_arg (arg2, POINTER_TYPE)))
      return 0;
  
    /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
    if (operand_equal_p (arg1, arg2, 0))
      return integer_zero_node;
*************** fold_builtin_strcmp (tree arglist)
*** 8083,8101 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_strncmp (tree arglist)
  {
-   tree arg1, arg2, len;
    const char *p1, *p2;
  
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   arg1 = TREE_VALUE (arglist);
-   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    /* If the LEN parameter is zero, return zero.  */
    if (integer_zerop (len))
      return omit_two_operands (integer_type_node, integer_zero_node,
--- 7933,7947 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_strncmp (tree arg1, tree arg2, tree len)
  {
    const char *p1, *p2;
  
!   if (! (validate_arg (arg1, POINTER_TYPE)
! 	 && validate_arg (arg2, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
      return 0;
  
    /* If the LEN parameter is zero, return zero.  */
    if (integer_zerop (len))
      return omit_two_operands (integer_type_node, integer_zero_node,
*************** fold_builtin_strncmp (tree arglist)
*** 8178,8193 ****
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_signbit (tree fndecl, tree arglist)
  {
!   tree type = TREE_TYPE (TREE_TYPE (fndecl));
!   tree arg, temp;
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
-   arg = TREE_VALUE (arglist);
- 
    /* If ARG is a compile-time constant, determine the result.  */
    if (TREE_CODE (arg) == REAL_CST
        && !TREE_CONSTANT_OVERFLOW (arg))
--- 8024,8036 ----
     NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_signbit (tree arg, tree type)
  {
!   tree temp;
  
!   if (!validate_arg (arg, REAL_TYPE))
      return NULL_TREE;
  
    /* If ARG is a compile-time constant, determine the result.  */
    if (TREE_CODE (arg) == REAL_CST
        && !TREE_CONSTANT_OVERFLOW (arg))
*************** fold_builtin_signbit (tree fndecl, tree 
*** 8215,8230 ****
     Return NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_copysign (tree fndecl, tree arglist, tree type)
  {
!   tree arg1, arg2, tem;
  
!   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
      return NULL_TREE;
  
-   arg1 = TREE_VALUE (arglist);
-   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
- 
    /* copysign(X,X) is X.  */
    if (operand_equal_p (arg1, arg2, 0))
      return fold_convert (type, arg1);
--- 8058,8070 ----
     Return NULL_TREE if no simplification can be made.  */
  
  static tree
! fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type)
  {
!   tree tem;
  
!   if (! (validate_arg (arg1, REAL_TYPE) && validate_arg (arg2, REAL_TYPE)))
      return NULL_TREE;
  
    /* copysign(X,X) is X.  */
    if (operand_equal_p (arg1, arg2, 0))
      return fold_convert (type, arg1);
*************** fold_builtin_copysign (tree fndecl, tree
*** 8254,8263 ****
    /* Strip sign changing operations for the first argument.  */
    tem = fold_strip_sign_ops (arg1);
    if (tem)
!     {
!       arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
!       return build_function_call_expr (fndecl, arglist);
!     }
  
    return NULL_TREE;
  }
--- 8094,8100 ----
    /* Strip sign changing operations for the first argument.  */
    tem = fold_strip_sign_ops (arg1);
    if (tem)
!     return build_call_expr (fndecl, 2, tem, arg2);
  
    return NULL_TREE;
  }
*************** fold_builtin_copysign (tree fndecl, tree
*** 8265,8279 ****
  /* Fold a call to builtin isascii.  */
  
  static tree
! fold_builtin_isascii (tree arglist)
  {
!   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
        /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
-       tree arg = TREE_VALUE (arglist);
- 
        arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
  		    build_int_cst (NULL_TREE,
  				   ~ (unsigned HOST_WIDE_INT) 0x7f));
--- 8102,8114 ----
  /* Fold a call to builtin isascii.  */
  
  static tree
! fold_builtin_isascii (tree arg)
  {
!   if (! validate_arg (arg, INTEGER_TYPE))
      return 0;
    else
      {
        /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
        arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
  		    build_int_cst (NULL_TREE,
  				   ~ (unsigned HOST_WIDE_INT) 0x7f));
*************** fold_builtin_isascii (tree arglist)
*** 8290,8304 ****
  /* Fold a call to builtin toascii.  */
  
  static tree
! fold_builtin_toascii (tree arglist)
  {
!   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
        /* Transform toascii(c) -> (c & 0x7f).  */
-       tree arg = TREE_VALUE (arglist);
- 
        return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
  			  build_int_cst (NULL_TREE, 0x7f));
      }
--- 8125,8137 ----
  /* Fold a call to builtin toascii.  */
  
  static tree
! fold_builtin_toascii (tree arg)
  {
!   if (! validate_arg (arg, INTEGER_TYPE))
      return 0;
    else
      {
        /* Transform toascii(c) -> (c & 0x7f).  */
        return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
  			  build_int_cst (NULL_TREE, 0x7f));
      }
*************** fold_builtin_toascii (tree arglist)
*** 8307,8329 ****
  /* Fold a call to builtin isdigit.  */
  
  static tree
! fold_builtin_isdigit (tree arglist)
  {
!   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
        /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
        /* According to the C standard, isdigit is unaffected by locale.
  	 However, it definitely is affected by the target character set.  */
-       tree arg;
        unsigned HOST_WIDE_INT target_digit0
  	= lang_hooks.to_target_charset ('0');
  
        if (target_digit0 == 0)
  	return NULL_TREE;
  
!       arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist));
        arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
  		    build_int_cst (unsigned_type_node, target_digit0));
        arg = fold_build2 (LE_EXPR, integer_type_node, arg,
--- 8140,8161 ----
  /* Fold a call to builtin isdigit.  */
  
  static tree
! fold_builtin_isdigit (tree arg)
  {
!   if (! validate_arg (arg, INTEGER_TYPE))
      return 0;
    else
      {
        /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
        /* According to the C standard, isdigit is unaffected by locale.
  	 However, it definitely is affected by the target character set.  */
        unsigned HOST_WIDE_INT target_digit0
  	= lang_hooks.to_target_charset ('0');
  
        if (target_digit0 == 0)
  	return NULL_TREE;
  
!       arg = fold_convert (unsigned_type_node, arg);
        arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
  		    build_int_cst (unsigned_type_node, target_digit0));
        arg = fold_build2 (LE_EXPR, integer_type_node, arg,
*************** fold_builtin_isdigit (tree arglist)
*** 8338,8351 ****
  /* Fold a call to fabs, fabsf or fabsl.  */
  
  static tree
! fold_builtin_fabs (tree arglist, tree type)
  {
!   tree arg;
! 
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      return 0;
  
-   arg = TREE_VALUE (arglist);
    arg = fold_convert (type, arg);
    if (TREE_CODE (arg) == REAL_CST)
      return fold_abs_const (arg, type);
--- 8170,8180 ----
  /* Fold a call to fabs, fabsf or fabsl.  */
  
  static tree
! fold_builtin_fabs (tree arg, tree type)
  {
!   if (!validate_arg (arg, REAL_TYPE))
      return 0;
  
    arg = fold_convert (type, arg);
    if (TREE_CODE (arg) == REAL_CST)
      return fold_abs_const (arg, type);
*************** fold_builtin_fabs (tree arglist, tree ty
*** 8355,8368 ****
  /* Fold a call to abs, labs, llabs or imaxabs.  */
  
  static tree
! fold_builtin_abs (tree arglist, tree type)
  {
!   tree arg;
! 
!   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   arg = TREE_VALUE (arglist);
    arg = fold_convert (type, arg);
    if (TREE_CODE (arg) == INTEGER_CST)
      return fold_abs_const (arg, type);
--- 8184,8194 ----
  /* Fold a call to abs, labs, llabs or imaxabs.  */
  
  static tree
! fold_builtin_abs (tree arg, tree type)
  {
!   if (!validate_arg (arg, INTEGER_TYPE))
      return 0;
  
    arg = fold_convert (type, arg);
    if (TREE_CODE (arg) == INTEGER_CST)
      return fold_abs_const (arg, type);
*************** fold_builtin_abs (tree arglist, tree typ
*** 8370,8408 ****
  }
  
  /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
!    EXP is the CALL_EXPR for the call.  */
  
  static tree
! fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
-   tree arg;
    REAL_VALUE_TYPE r;
  
!   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
      {
!       /* Check that we have exactly one argument.  */
!       if (arglist == 0)
! 	{
! 	  error ("too few arguments to function %qs",
! 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 	  return error_mark_node;
! 	}
!       else if (TREE_CHAIN (arglist) != 0)
! 	{
! 	  error ("too many arguments to function %qs",
! 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 	  return error_mark_node;
! 	}
!       else
! 	{
! 	  error ("non-floating-point argument to function %qs",
! 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 	  return error_mark_node;
! 	}
      }
  
-   arg = TREE_VALUE (arglist);
    switch (builtin_index)
      {
      case BUILT_IN_ISINF:
--- 8196,8216 ----
  }
  
  /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
!    ARG is the argument for the call.  */
  
  static tree
! fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    REAL_VALUE_TYPE r;
  
!   if (!validate_arg (arg, REAL_TYPE))
      {
!       error ("non-floating-point argument to function %qs",
! 	     IDENTIFIER_POINTER (DECL_NAME (fndecl)));
!       return error_mark_node;
      }
  
    switch (builtin_index)
      {
      case BUILT_IN_ISINF:
*************** fold_builtin_classify (tree fndecl, tree
*** 8455,8498 ****
  
  /* Fold a call to an unordered comparison function such as
     __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
!    being called and ARGLIST is the argument list for the call.
     UNORDERED_CODE and ORDERED_CODE are comparison codes that give
     the opposite of the desired result.  UNORDERED_CODE is used
     for modes that can hold NaNs and ORDERED_CODE is used for
     the rest.  */
  
  static tree
! fold_builtin_unordered_cmp (tree fndecl, tree arglist,
  			    enum tree_code unordered_code,
  			    enum tree_code ordered_code)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum tree_code code;
-   tree arg0, arg1;
    tree type0, type1;
    enum tree_code code0, code1;
    tree cmp_type = NULL_TREE;
  
-   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
-     {
-       /* Check that we have exactly two arguments.  */
-       if (arglist == 0 || TREE_CHAIN (arglist) == 0)
- 	{
- 	  error ("too few arguments to function %qs",
- 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
- 	  return error_mark_node;
- 	}
-       else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
- 	{
- 	  error ("too many arguments to function %qs",
- 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
- 	  return error_mark_node;
- 	}
-     }
- 
-   arg0 = TREE_VALUE (arglist);
-   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- 
    type0 = TREE_TYPE (arg0);
    type1 = TREE_TYPE (arg1);
  
--- 8263,8285 ----
  
  /* Fold a call to an unordered comparison function such as
     __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
!    being called and ARG0 and ARG1 are the arguments for the call.
     UNORDERED_CODE and ORDERED_CODE are comparison codes that give
     the opposite of the desired result.  UNORDERED_CODE is used
     for modes that can hold NaNs and ORDERED_CODE is used for
     the rest.  */
  
  static tree
! fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1,
  			    enum tree_code unordered_code,
  			    enum tree_code ordered_code)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum tree_code code;
    tree type0, type1;
    enum tree_code code0, code1;
    tree cmp_type = NULL_TREE;
  
    type0 = TREE_TYPE (arg0);
    type1 = TREE_TYPE (arg1);
  
*************** fold_builtin_unordered_cmp (tree fndecl,
*** 8536,8608 ****
     if no simplification was possible.  */
  
  static tree
! fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
!   enum built_in_function fcode;
! 
!   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
!     return targetm.fold_builtin (fndecl, arglist, ignore);
! 
!   fcode = DECL_FUNCTION_CODE (fndecl);
    switch (fcode)
      {
!     case BUILT_IN_FPUTS:
!       return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
! 
!     case BUILT_IN_FPUTS_UNLOCKED:
!       return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
! 
!     case BUILT_IN_STRSTR:
!       return fold_builtin_strstr (arglist, type);
! 
!     case BUILT_IN_STRCAT:
!       return fold_builtin_strcat (arglist);
! 
!     case BUILT_IN_STRNCAT:
!       return fold_builtin_strncat (arglist);
! 
!     case BUILT_IN_STRSPN:
!       return fold_builtin_strspn (arglist);
! 
!     case BUILT_IN_STRCSPN:
!       return fold_builtin_strcspn (arglist);
! 
!     case BUILT_IN_STRCHR:
!     case BUILT_IN_INDEX:
!       return fold_builtin_strchr (arglist, type);
! 
!     case BUILT_IN_STRRCHR:
!     case BUILT_IN_RINDEX:
!       return fold_builtin_strrchr (arglist, type);
! 
!     case BUILT_IN_STRCPY:
!       return fold_builtin_strcpy (fndecl, arglist, NULL_TREE);
! 
!     case BUILT_IN_STRNCPY:
!       return fold_builtin_strncpy (fndecl, arglist, NULL_TREE);
! 
!     case BUILT_IN_STRCMP:
!       return fold_builtin_strcmp (arglist);
  
!     case BUILT_IN_STRNCMP:
!       return fold_builtin_strncmp (arglist);
  
!     case BUILT_IN_STRPBRK:
!       return fold_builtin_strpbrk (arglist, type);
  
!     case BUILT_IN_BCMP:
!     case BUILT_IN_MEMCMP:
!       return fold_builtin_memcmp (arglist);
  
!     case BUILT_IN_SPRINTF:
!       return fold_builtin_sprintf (arglist, ignore);
  
      case BUILT_IN_CONSTANT_P:
        {
! 	tree val;
  
- 	val = fold_builtin_constant_p (arglist);
  	/* Gimplification will pull the CALL_EXPR for the builtin out of
  	   an if condition.  When not optimizing, we'll not CSE it back.
  	   To avoid link error types of regressions, return false now.  */
--- 8323,8364 ----
     if no simplification was possible.  */
  
  static tree
! fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
!   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    switch (fcode)
      {
!     CASE_FLT_FN (BUILT_IN_INF):
!     case BUILT_IN_INFD32:
!     case BUILT_IN_INFD64:
!     case BUILT_IN_INFD128:
!       return fold_builtin_inf (type, true);
  
!     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
!       return fold_builtin_inf (type, false);
  
!     case BUILT_IN_CLASSIFY_TYPE:
!       return fold_builtin_classify_type (NULL_TREE);
  
!     default:
!       break;
!     }
!   return 0;
! }
  
! static tree
! fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
! {
!   tree type = TREE_TYPE (TREE_TYPE (fndecl));
!   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
!   switch (fcode)
!     {
  
      case BUILT_IN_CONSTANT_P:
        {
! 	tree val = fold_builtin_constant_p (arg0);
  
  	/* Gimplification will pull the CALL_EXPR for the builtin out of
  	   an if condition.  When not optimizing, we'll not CSE it back.
  	   To avoid link error types of regressions, return false now.  */
*************** fold_builtin_1 (tree fndecl, tree arglis
*** 8612,8731 ****
  	return val;
        }
  
-     case BUILT_IN_EXPECT:
-       return fold_builtin_expect (arglist);
- 
      case BUILT_IN_CLASSIFY_TYPE:
!       return fold_builtin_classify_type (arglist);
  
      case BUILT_IN_STRLEN:
!       return fold_builtin_strlen (arglist);
  
      CASE_FLT_FN (BUILT_IN_FABS):
!       return fold_builtin_fabs (arglist, type);
  
      case BUILT_IN_ABS:
      case BUILT_IN_LABS:
      case BUILT_IN_LLABS:
      case BUILT_IN_IMAXABS:
!       return fold_builtin_abs (arglist, type);
  
      CASE_FLT_FN (BUILT_IN_CONJ):
!       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
! 	return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
        break;
  
      CASE_FLT_FN (BUILT_IN_CREAL):
!       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
! 	return non_lvalue (fold_build1 (REALPART_EXPR, type,
! 					TREE_VALUE (arglist)));
        break;
  
      CASE_FLT_FN (BUILT_IN_CIMAG):
!       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
! 	return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
! 					TREE_VALUE (arglist)));
        break;
  
      CASE_FLT_FN (BUILT_IN_CABS):
!       return fold_builtin_cabs (arglist, type);
  
      CASE_FLT_FN (BUILT_IN_SQRT):
!       return fold_builtin_sqrt (arglist, type);
  
      CASE_FLT_FN (BUILT_IN_CBRT):
!       return fold_builtin_cbrt (arglist, type);
  
      CASE_FLT_FN (BUILT_IN_SIN):
!       return fold_builtin_sin (arglist);
  
      CASE_FLT_FN (BUILT_IN_COS):
!       return fold_builtin_cos (arglist, type, fndecl);
  
      CASE_FLT_FN (BUILT_IN_EXP):
!       return fold_builtin_exponent (fndecl, arglist, &dconste);
  
      CASE_FLT_FN (BUILT_IN_EXP2):
!       return fold_builtin_exponent (fndecl, arglist, &dconst2);
  
      CASE_FLT_FN (BUILT_IN_EXP10):
      CASE_FLT_FN (BUILT_IN_POW10):
!       return fold_builtin_exponent (fndecl, arglist, &dconst10);
  
      CASE_FLT_FN (BUILT_IN_LOG):
!       return fold_builtin_logarithm (fndecl, arglist, &dconste);
  
      CASE_FLT_FN (BUILT_IN_LOG2):
!       return fold_builtin_logarithm (fndecl, arglist, &dconst2);
  
      CASE_FLT_FN (BUILT_IN_LOG10):
!       return fold_builtin_logarithm (fndecl, arglist, &dconst10);
  
      CASE_FLT_FN (BUILT_IN_TAN):
!       return fold_builtin_tan (arglist);
  
      CASE_FLT_FN (BUILT_IN_ATAN):
!       return fold_builtin_atan (arglist, type);
! 
!     CASE_FLT_FN (BUILT_IN_POW):
!       return fold_builtin_pow (fndecl, arglist, type);
! 
!     CASE_FLT_FN (BUILT_IN_POWI):
!       return fold_builtin_powi (fndecl, arglist, type);
! 
!     CASE_FLT_FN (BUILT_IN_INF):
!     case BUILT_IN_INFD32:
!     case BUILT_IN_INFD64:
!     case BUILT_IN_INFD128:
!       return fold_builtin_inf (type, true);
! 
!     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
!       return fold_builtin_inf (type, false);
  
      CASE_FLT_FN (BUILT_IN_NAN):
      case BUILT_IN_NAND32:
      case BUILT_IN_NAND64:
      case BUILT_IN_NAND128:
!       return fold_builtin_nan (arglist, type, true);
  
      CASE_FLT_FN (BUILT_IN_NANS):
!       return fold_builtin_nan (arglist, type, false);
  
      CASE_FLT_FN (BUILT_IN_FLOOR):
!       return fold_builtin_floor (fndecl, arglist);
  
      CASE_FLT_FN (BUILT_IN_CEIL):
!       return fold_builtin_ceil (fndecl, arglist);
  
      CASE_FLT_FN (BUILT_IN_TRUNC):
!       return fold_builtin_trunc (fndecl, arglist);
  
      CASE_FLT_FN (BUILT_IN_ROUND):
!       return fold_builtin_round (fndecl, arglist);
  
      CASE_FLT_FN (BUILT_IN_NEARBYINT):
      CASE_FLT_FN (BUILT_IN_RINT):
!       return fold_trunc_transparent_mathfn (fndecl, arglist);
  
      CASE_FLT_FN (BUILT_IN_LCEIL):
      CASE_FLT_FN (BUILT_IN_LLCEIL):
--- 8368,8467 ----
  	return val;
        }
  
      case BUILT_IN_CLASSIFY_TYPE:
!       return fold_builtin_classify_type (arg0);
  
      case BUILT_IN_STRLEN:
!       return fold_builtin_strlen (arg0);
  
      CASE_FLT_FN (BUILT_IN_FABS):
!       return fold_builtin_fabs (arg0, type);
  
      case BUILT_IN_ABS:
      case BUILT_IN_LABS:
      case BUILT_IN_LLABS:
      case BUILT_IN_IMAXABS:
!       return fold_builtin_abs (arg0, type);
  
      CASE_FLT_FN (BUILT_IN_CONJ):
!       if (validate_arg (arg0, COMPLEX_TYPE))
! 	return fold_build1 (CONJ_EXPR, type, arg0);
        break;
  
      CASE_FLT_FN (BUILT_IN_CREAL):
!       if (validate_arg (arg0, COMPLEX_TYPE))
! 	return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));
        break;
  
      CASE_FLT_FN (BUILT_IN_CIMAG):
!       if (validate_arg (arg0, COMPLEX_TYPE))
! 	return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0));
        break;
  
      CASE_FLT_FN (BUILT_IN_CABS):
!       return fold_builtin_cabs (arg0, type);
  
      CASE_FLT_FN (BUILT_IN_SQRT):
!       return fold_builtin_sqrt (arg0, type);
  
      CASE_FLT_FN (BUILT_IN_CBRT):
!       return fold_builtin_cbrt (arg0, type);
  
      CASE_FLT_FN (BUILT_IN_SIN):
!       return fold_builtin_sin (arg0);
  
      CASE_FLT_FN (BUILT_IN_COS):
!       return fold_builtin_cos (arg0, type, fndecl);
  
      CASE_FLT_FN (BUILT_IN_EXP):
!       return fold_builtin_exponent (fndecl, arg0, &dconste);
  
      CASE_FLT_FN (BUILT_IN_EXP2):
!       return fold_builtin_exponent (fndecl, arg0, &dconst2);
  
      CASE_FLT_FN (BUILT_IN_EXP10):
      CASE_FLT_FN (BUILT_IN_POW10):
!       return fold_builtin_exponent (fndecl, arg0, &dconst10);
  
      CASE_FLT_FN (BUILT_IN_LOG):
!       return fold_builtin_logarithm (fndecl, arg0, &dconste);
  
      CASE_FLT_FN (BUILT_IN_LOG2):
!       return fold_builtin_logarithm (fndecl, arg0, &dconst2);
  
      CASE_FLT_FN (BUILT_IN_LOG10):
!       return fold_builtin_logarithm (fndecl, arg0, &dconst10);
  
      CASE_FLT_FN (BUILT_IN_TAN):
!       return fold_builtin_tan (arg0);
  
      CASE_FLT_FN (BUILT_IN_ATAN):
!       return fold_builtin_atan (arg0, type);
  
      CASE_FLT_FN (BUILT_IN_NAN):
      case BUILT_IN_NAND32:
      case BUILT_IN_NAND64:
      case BUILT_IN_NAND128:
!       return fold_builtin_nan (arg0, type, true);
  
      CASE_FLT_FN (BUILT_IN_NANS):
!       return fold_builtin_nan (arg0, type, false);
  
      CASE_FLT_FN (BUILT_IN_FLOOR):
!       return fold_builtin_floor (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_CEIL):
!       return fold_builtin_ceil (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_TRUNC):
!       return fold_builtin_trunc (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_ROUND):
!       return fold_builtin_round (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_NEARBYINT):
      CASE_FLT_FN (BUILT_IN_RINT):
!       return fold_trunc_transparent_mathfn (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_LCEIL):
      CASE_FLT_FN (BUILT_IN_LLCEIL):
*************** fold_builtin_1 (tree fndecl, tree arglis
*** 8733,8902 ****
      CASE_FLT_FN (BUILT_IN_LLFLOOR):
      CASE_FLT_FN (BUILT_IN_LROUND):
      CASE_FLT_FN (BUILT_IN_LLROUND):
!       return fold_builtin_int_roundingfn (fndecl, arglist);
  
      CASE_FLT_FN (BUILT_IN_LRINT):
      CASE_FLT_FN (BUILT_IN_LLRINT):
!       return fold_fixed_mathfn (fndecl, arglist);
  
      CASE_INT_FN (BUILT_IN_FFS):
      CASE_INT_FN (BUILT_IN_CLZ):
      CASE_INT_FN (BUILT_IN_CTZ):
      CASE_INT_FN (BUILT_IN_POPCOUNT):
      CASE_INT_FN (BUILT_IN_PARITY):
!       return fold_builtin_bitop (fndecl, arglist);
! 
!     case BUILT_IN_MEMCPY:
!       return fold_builtin_memcpy (fndecl, arglist);
! 
!     case BUILT_IN_MEMPCPY:
!       return fold_builtin_mempcpy (arglist, type, /*endp=*/1);
! 
!     case BUILT_IN_MEMMOVE:
!       return fold_builtin_memmove (arglist, type);
  
      CASE_FLT_FN (BUILT_IN_SIGNBIT):
!       return fold_builtin_signbit (fndecl, arglist);
  
      case BUILT_IN_ISASCII:
!       return fold_builtin_isascii (arglist);
  
      case BUILT_IN_TOASCII:
!       return fold_builtin_toascii (arglist);
  
      case BUILT_IN_ISDIGIT:
!       return fold_builtin_isdigit (arglist);
! 
!     CASE_FLT_FN (BUILT_IN_COPYSIGN):
!       return fold_builtin_copysign (fndecl, arglist, type);
  
      CASE_FLT_FN (BUILT_IN_FINITE):
      case BUILT_IN_FINITED32:
      case BUILT_IN_FINITED64:
      case BUILT_IN_FINITED128:
!       return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
  
      CASE_FLT_FN (BUILT_IN_ISINF):
      case BUILT_IN_ISINFD32:
      case BUILT_IN_ISINFD64:
      case BUILT_IN_ISINFD128:
!       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
  
      CASE_FLT_FN (BUILT_IN_ISNAN):
      case BUILT_IN_ISNAND32:
      case BUILT_IN_ISNAND64:
      case BUILT_IN_ISNAND128:
!       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
  
      case BUILT_IN_ISGREATER:
!       return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR);
      case BUILT_IN_ISGREATEREQUAL:
!       return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR);
      case BUILT_IN_ISLESS:
!       return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR);
      case BUILT_IN_ISLESSEQUAL:
!       return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR);
      case BUILT_IN_ISLESSGREATER:
!       return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR);
      case BUILT_IN_ISUNORDERED:
!       return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
! 					 NOP_EXPR);
! 
        /* We do the folding for va_start in the expander.  */
      case BUILT_IN_VA_START:
        break;
  
      case BUILT_IN_OBJECT_SIZE:
!       return fold_builtin_object_size (arglist);
!     case BUILT_IN_MEMCPY_CHK:
!     case BUILT_IN_MEMPCPY_CHK:
!     case BUILT_IN_MEMMOVE_CHK:
!     case BUILT_IN_MEMSET_CHK:
!       return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore,
! 				      DECL_FUNCTION_CODE (fndecl));
!     case BUILT_IN_STRCPY_CHK:
!     case BUILT_IN_STPCPY_CHK:
!       return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore,
! 				      DECL_FUNCTION_CODE (fndecl));
!     case BUILT_IN_STRNCPY_CHK:
!       return fold_builtin_strncpy_chk (arglist, NULL_TREE);
!     case BUILT_IN_STRCAT_CHK:
!       return fold_builtin_strcat_chk (fndecl, arglist);
!     case BUILT_IN_STRNCAT_CHK:
!       return fold_builtin_strncat_chk (fndecl, arglist);
!     case BUILT_IN_SPRINTF_CHK:
!     case BUILT_IN_VSPRINTF_CHK:
!       return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl));
!     case BUILT_IN_SNPRINTF_CHK:
!     case BUILT_IN_VSNPRINTF_CHK:
!       return fold_builtin_snprintf_chk (arglist, NULL_TREE,
! 					DECL_FUNCTION_CODE (fndecl));
  
      case BUILT_IN_PRINTF:
      case BUILT_IN_PRINTF_UNLOCKED:
      case BUILT_IN_VPRINTF:
      case BUILT_IN_PRINTF_CHK:
      case BUILT_IN_VPRINTF_CHK:
!       return fold_builtin_printf (fndecl, arglist, ignore,
! 				  DECL_FUNCTION_CODE (fndecl));
  
      case BUILT_IN_FPRINTF:
      case BUILT_IN_FPRINTF_UNLOCKED:
      case BUILT_IN_VFPRINTF:
      case BUILT_IN_FPRINTF_CHK:
      case BUILT_IN_VFPRINTF_CHK:
!       return fold_builtin_fprintf (fndecl, arglist, ignore,
! 				   DECL_FUNCTION_CODE (fndecl));
  
      default:
        break;
      }
  
    return 0;
  }
  
  /* A wrapper function for builtin folding that prevents warnings for
     "statement without effect" and the like, caused by removing the
     call node earlier than the warning is generated.  */
  
  tree
! fold_builtin (tree fndecl, tree arglist, bool ignore)
  {
!   tree exp = fold_builtin_1 (fndecl, arglist, ignore);
!   if (exp)
      {
!       exp = build1 (NOP_EXPR, TREE_TYPE (exp), exp);
!       TREE_NO_WARNING (exp) = 1;
      }
  
    return exp;
  }
  
! /* Conveniently construct a function call expression.  */
  
! tree
! build_function_call_expr (tree fn, tree arglist)
  {
!   tree call_expr;
  
!   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
!   return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
! 		      call_expr, arglist, NULL_TREE);
  }
  
  /* This function validates the types of a function call argument list
!    represented as a tree chain of parameters against a specified list
!    of tree_codes.  If the last specifier is a 0, that represents an
!    ellipses, otherwise the last specifier must be a VOID_TYPE.  */
  
  static int
! validate_arglist (tree arglist, ...)
  {
    enum tree_code code;
    int res = 0;
    va_list ap;
  
!   va_start (ap, arglist);
  
    do
      {
--- 8469,9045 ----
      CASE_FLT_FN (BUILT_IN_LLFLOOR):
      CASE_FLT_FN (BUILT_IN_LROUND):
      CASE_FLT_FN (BUILT_IN_LLROUND):
!       return fold_builtin_int_roundingfn (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_LRINT):
      CASE_FLT_FN (BUILT_IN_LLRINT):
!       return fold_fixed_mathfn (fndecl, arg0);
  
      CASE_INT_FN (BUILT_IN_FFS):
      CASE_INT_FN (BUILT_IN_CLZ):
      CASE_INT_FN (BUILT_IN_CTZ):
      CASE_INT_FN (BUILT_IN_POPCOUNT):
      CASE_INT_FN (BUILT_IN_PARITY):
!       return fold_builtin_bitop (fndecl, arg0);
  
      CASE_FLT_FN (BUILT_IN_SIGNBIT):
!       return fold_builtin_signbit (arg0, type);
  
      case BUILT_IN_ISASCII:
!       return fold_builtin_isascii (arg0);
  
      case BUILT_IN_TOASCII:
!       return fold_builtin_toascii (arg0);
  
      case BUILT_IN_ISDIGIT:
!       return fold_builtin_isdigit (arg0);
  
      CASE_FLT_FN (BUILT_IN_FINITE):
      case BUILT_IN_FINITED32:
      case BUILT_IN_FINITED64:
      case BUILT_IN_FINITED128:
!       return fold_builtin_classify (fndecl, arg0, BUILT_IN_FINITE);
  
      CASE_FLT_FN (BUILT_IN_ISINF):
      case BUILT_IN_ISINFD32:
      case BUILT_IN_ISINFD64:
      case BUILT_IN_ISINFD128:
!       return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF);
  
      CASE_FLT_FN (BUILT_IN_ISNAN):
      case BUILT_IN_ISNAND32:
      case BUILT_IN_ISNAND64:
      case BUILT_IN_ISNAND128:
!       return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
! 
!     case BUILT_IN_PRINTF:
!     case BUILT_IN_PRINTF_UNLOCKED:
!     case BUILT_IN_VPRINTF:
!       return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode);
! 
!     default:
!       break;
!     }
! 
!   return 0;
! }
! 
! static tree
! fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
! {
!   tree type = TREE_TYPE (TREE_TYPE (fndecl));
!   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
!   switch (fcode)
!     {
! 
!     case BUILT_IN_FPUTS:
!       return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE);
! 
!     case BUILT_IN_FPUTS_UNLOCKED:
!       return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE);
! 
!     case BUILT_IN_STRSTR:
!       return fold_builtin_strstr (arg0, arg1, type);
! 
!     case BUILT_IN_STRCAT:
!       return fold_builtin_strcat (arg0, arg1);
! 
!     case BUILT_IN_STRSPN:
!       return fold_builtin_strspn (arg0, arg1);
! 
!     case BUILT_IN_STRCSPN:
!       return fold_builtin_strcspn (arg0, arg1);
! 
!     case BUILT_IN_STRCHR:
!     case BUILT_IN_INDEX:
!       return fold_builtin_strchr (arg0, arg1, type);
! 
!     case BUILT_IN_STRRCHR:
!     case BUILT_IN_RINDEX:
!       return fold_builtin_strrchr (arg0, arg1, type);
! 
!     case BUILT_IN_STRCPY:
!       return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE);
! 
!     case BUILT_IN_STRCMP:
!       return fold_builtin_strcmp (arg0, arg1);
! 
!     case BUILT_IN_STRPBRK:
!       return fold_builtin_strpbrk (arg0, arg1, type);
! 
!     case BUILT_IN_EXPECT:
!       return fold_builtin_expect (arg0);
! 
!     CASE_FLT_FN (BUILT_IN_POW):
!       return fold_builtin_pow (fndecl, arg0, arg1, type);
! 
!     CASE_FLT_FN (BUILT_IN_POWI):
!       return fold_builtin_powi (fndecl, arg0, arg1, type);
! 
!     CASE_FLT_FN (BUILT_IN_COPYSIGN):
!       return fold_builtin_copysign (fndecl, arg0, arg1, type);
  
      case BUILT_IN_ISGREATER:
!       return fold_builtin_unordered_cmp (fndecl, arg0, arg1,
! 					 UNLE_EXPR, LE_EXPR);
      case BUILT_IN_ISGREATEREQUAL:
!       return fold_builtin_unordered_cmp (fndecl, arg0, arg1,
! 					 UNLT_EXPR, LT_EXPR);
      case BUILT_IN_ISLESS:
!       return fold_builtin_unordered_cmp (fndecl, arg0, arg1,
! 					 UNGE_EXPR, GE_EXPR);
      case BUILT_IN_ISLESSEQUAL:
!       return fold_builtin_unordered_cmp (fndecl, arg0, arg1,
! 					 UNGT_EXPR, GT_EXPR);
      case BUILT_IN_ISLESSGREATER:
!       return fold_builtin_unordered_cmp (fndecl, arg0, arg1,
! 					 UNEQ_EXPR, EQ_EXPR);
      case BUILT_IN_ISUNORDERED:
!       return fold_builtin_unordered_cmp (fndecl, arg0, arg1,
! 					 UNORDERED_EXPR, NOP_EXPR);
        /* We do the folding for va_start in the expander.  */
      case BUILT_IN_VA_START:
        break;
  
+     case BUILT_IN_SPRINTF:
+       return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore);
+ 
      case BUILT_IN_OBJECT_SIZE:
!       return fold_builtin_object_size (arg0, arg1);
  
      case BUILT_IN_PRINTF:
      case BUILT_IN_PRINTF_UNLOCKED:
      case BUILT_IN_VPRINTF:
+       return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode);
+ 
      case BUILT_IN_PRINTF_CHK:
      case BUILT_IN_VPRINTF_CHK:
!       if (! validate_arg (arg0, INTEGER_TYPE) || TREE_SIDE_EFFECTS (arg0))
! 	return 0;
!       else
! 	return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode);
  
      case BUILT_IN_FPRINTF:
      case BUILT_IN_FPRINTF_UNLOCKED:
      case BUILT_IN_VFPRINTF:
+       return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE,
+ 				   ignore, fcode);
+ 
+ 
+     default:
+       break;
+     }
+   return 0;
+ }
+ 
+ static tree
+ fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore)
+ {
+   tree type = TREE_TYPE (TREE_TYPE (fndecl));
+   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+   switch (fcode)
+     {
+ 
+     case BUILT_IN_STRNCAT:
+       return fold_builtin_strncat (arg0, arg1, arg2);
+ 
+     case BUILT_IN_STRNCPY:
+       return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE);
+ 
+     case BUILT_IN_STRNCMP:
+       return fold_builtin_strncmp (arg0, arg1, arg2);
+ 
+     case BUILT_IN_BCMP:
+     case BUILT_IN_MEMCMP:
+       return fold_builtin_memcmp (arg0, arg1, arg2);
+ 
+     case BUILT_IN_MEMCPY:
+       return fold_builtin_memcpy (arg0, arg1, arg2, type);
+ 
+     case BUILT_IN_MEMPCPY:
+       return fold_builtin_mempcpy (arg0, arg1, arg2, type, 1);
+ 
+     case BUILT_IN_MEMMOVE:
+       return fold_builtin_memmove (arg0, arg1, arg2, type);
+ 
+     case BUILT_IN_SPRINTF:
+       return fold_builtin_sprintf (arg0, arg1, arg2, ignore);
+ 
+     case BUILT_IN_STRCPY_CHK:
+     case BUILT_IN_STPCPY_CHK:
+       return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE,
+ 				      ignore, fcode);
+ 
+     case BUILT_IN_STRCAT_CHK:
+       return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2);
+ 
+     case BUILT_IN_PRINTF_CHK:
+     case BUILT_IN_VPRINTF_CHK:
+       if (! validate_arg (arg0, INTEGER_TYPE) || TREE_SIDE_EFFECTS (arg0))
+ 	return 0;
+       else
+ 	return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode);
+ 
+     case BUILT_IN_FPRINTF:
+     case BUILT_IN_FPRINTF_UNLOCKED:
+     case BUILT_IN_VFPRINTF:
+       return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode);
+ 
      case BUILT_IN_FPRINTF_CHK:
      case BUILT_IN_VFPRINTF_CHK:
!       if (! validate_arg (arg1, INTEGER_TYPE) || TREE_SIDE_EFFECTS (arg1))
! 	return 0;
!       else
! 	return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE,
! 				     ignore, fcode);
  
      default:
        break;
      }
+   return 0;
+ }
+ 
+ static tree
+ fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3,
+ 		bool ignore)
+ {
+   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ 
+   switch (fcode)
+     {
+     case BUILT_IN_MEMCPY_CHK:
+     case BUILT_IN_MEMPCPY_CHK:
+     case BUILT_IN_MEMMOVE_CHK:
+     case BUILT_IN_MEMSET_CHK:
+       return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3,
+ 				      NULL_TREE, ignore,
+ 				      DECL_FUNCTION_CODE (fndecl));
+ 
+     case BUILT_IN_STRNCPY_CHK:
+       return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE);
+ 
+     case BUILT_IN_STRNCAT_CHK:
+       return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3);
  
+     case BUILT_IN_FPRINTF_CHK:
+     case BUILT_IN_VFPRINTF_CHK:
+       if (! validate_arg (arg1, INTEGER_TYPE) || TREE_SIDE_EFFECTS (arg1))
+ 	return 0;
+       else
+ 	return fold_builtin_fprintf (fndecl, arg0, arg2, arg3,
+ 				     ignore, fcode);
+     default:
+       break;
+     }
    return 0;
  }
  
+ /* Dispatch to folders for builtins that match on patterns with a fixed
+    number of arguments.
+ */
+ 
+ static tree
+ fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore)
+ {
+   tree ret = NULL_TREE;
+   switch (nargs)
+     {
+     case 0:
+       ret = fold_builtin_0 (fndecl, ignore);
+       break;
+     case 1:
+       ret = fold_builtin_1 (fndecl, args[0], ignore);
+       break;
+     case 2:
+       ret = fold_builtin_2 (fndecl, args[0], args[1], ignore);
+       break;
+     case 3:
+       ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore);
+       break;
+     case 4:
+       ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3],
+ 			    ignore);
+       break;
+     default:
+       break;
+     }
+   if (ret)
+     {
+       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+       TREE_NO_WARNING (ret) = 1;
+       return ret;
+     }
+   return NULL_TREE;
+ }
+ 
+ 
+ /* Builtins with folding operations that operate on "..." arguments
+    need special handling; we need to store the arguments in a convenient
+    data structure before attempting any folding.  Fortunately there are
+    only a few builtins that fall into this category.
+ */
+ 
+ static tree
+ fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED)
+ {
+   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+   tree ret = NULL_TREE;
+ 
+   switch (fcode)
+     {
+     case BUILT_IN_SPRINTF_CHK:
+     case BUILT_IN_VSPRINTF_CHK:
+       ret = fold_builtin_sprintf_chk (exp, fcode);
+       break;
+ 
+     case BUILT_IN_SNPRINTF_CHK:
+     case BUILT_IN_VSNPRINTF_CHK:
+       ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode);
+ 
+     default:
+       break;
+     }
+   if (ret)
+     {
+       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+       TREE_NO_WARNING (ret) = 1;
+       return ret;
+     }
+   return 0;
+ }
+ 
+ 
  /* A wrapper function for builtin folding that prevents warnings for
     "statement without effect" and the like, caused by removing the
     call node earlier than the warning is generated.  */
  
  tree
! fold_call_expr (tree exp, bool ignore)
  {
!   tree ret = NULL_TREE;
!   tree fn = CALL_EXPR_FN (exp);
!   if (TREE_CODE (fn) == ADDR_EXPR)
!     {
!       tree fndecl = TREE_OPERAND (fn, 0);
!       if ((TREE_CODE (fndecl) == FUNCTION_DECL)
! 	  && DECL_BUILT_IN (fndecl))
! 	{
! 	  /* *** This interface really needs to be fixed not to use a list */
! 	  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
! 	    return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
! 
! 	  else
! 	    {
! 	      int nargs = call_expr_nargs (exp);
! 	      if (nargs <= 4)
! 		{
! 		  int i;
! 		  tree args[4];
! 		  for (i = 0; i < nargs; i++)
! 		    args[i] = call_expr_arg (exp, i);
! 		  ret = fold_builtin_n (fndecl, args, nargs, ignore);
! 		  if (ret)
! 		    return ret;
! 		}
! 	      return fold_builtin_varargs (fndecl, exp, ignore);
! 	    }
! 	}
!     }
!   return NULL_TREE;
! }
! 
! 
! /* Conveniently construct a function call expression.  */
! 
! tree
! build_function_call_expr (tree fndecl, tree arglist)
! {
!   tree fntype = TREE_TYPE (fndecl);
!   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
!   return fold_build_call_expr (TREE_TYPE (fntype), fn, arglist, NULL_TREE);
! }
! 
! 
! /* A more general constructor */
! 
! tree
! fold_build_call_expr (tree type, tree fn, tree arglist, tree static_chain)
! {
!   tree ret = NULL_TREE;
!   if (TREE_CODE (fn) == ADDR_EXPR)
      {
!       tree fndecl = TREE_OPERAND (fn, 0);
!       if ((TREE_CODE (fndecl) == FUNCTION_DECL)
! 	  && DECL_BUILT_IN (fndecl))
! 	{
! 	  /* *** This interface really needs to be fixed not to use a list */
! 	  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
! 	    {
! 	      ret = targetm.fold_builtin (fndecl, arglist, false);
! 	      if (ret)
! 		return ret;
! 	    }
! 	  else
! 	    {
! 	      tree tail = arglist;
! 	      tree args[4];
! 	      int nargs;
! 	      tree temp;
! 	      for (nargs = 0; nargs < 4; nargs++)
! 		{
! 		  if (!tail)
! 		    break;
! 		  args[nargs] = TREE_VALUE (tail);
! 		  tail = TREE_CHAIN (tail);
! 		}
! 	      if (nargs <= 4)
! 		{
! 		  ret = fold_builtin_n (fndecl, args, nargs, false);
! 		  if (ret)
! 		    return ret;
! 		}
! 	      temp = build3 (CALL_EXPR, type, fn, arglist, static_chain);
! 	      ret = fold_builtin_varargs (fndecl, temp, false);
! 	      if (ret)
! 		return ret;
! 	      else
! 		return temp;
! 	    }
! 	}
!     }
!   return build3 (CALL_EXPR, type, fn, arglist, static_chain);
! }
! 
! /* Likewise, but passing the argument expressions individually instead of
!    as a TREE_LIST.  This is the preferred interface. */
! 
! tree
! build_call_expr (tree fndecl, int n, ...)
! {
!   va_list ap;
!   int i;
!   tree arglist = NULL_TREE;
!   tree ret = NULL_TREE;
!   tree exp;
!   tree fntype;
! 
!   if ((TREE_CODE (fndecl) == FUNCTION_DECL)
!       && DECL_BUILT_IN (fndecl)
!       && (n <= 4)
!       && (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD))
!     
!     {
!       /* First try the transformations that don't require consing up
! 	 an arglist or exp. */
!       tree args[4];
!       va_start (ap, n);
!       for (i = 0; i < n; i++)
! 	args[i] = va_arg (ap, tree);
!       va_end (ap);
!       ret = fold_builtin_n (fndecl, args, n, false);
!       if (ret)
! 	return ret;
!     }
! 
!   /* We at least need an arglist.... */
!   va_start (ap, n);
!   for (i = 0; i < n; i++)
!     {
!       tree arg = va_arg (ap, tree);
!       arglist = tree_cons (NULL_TREE, arg, arglist);
!     }
!   va_end (ap);
!   arglist = nreverse (arglist);
! 
!   if ((TREE_CODE (fndecl) == FUNCTION_DECL)
!       && DECL_BUILT_IN (fndecl)
!       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
!     {
!       ret = targetm.fold_builtin (fndecl, arglist, false);
!       if (ret)
! 	return ret;
!     }
! 
!   /* If we got this far, we need to build an exp. */
!   fntype = TREE_TYPE (fndecl);
!   exp = build3 (CALL_EXPR,
! 		TREE_TYPE (fntype),
! 		build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl),
! 		arglist, NULL_TREE);
! 
!   if ((TREE_CODE (fndecl) == FUNCTION_DECL)
!       && DECL_BUILT_IN (fndecl))
!     {
!       ret = fold_builtin_varargs (fndecl, exp, false);
!       if (ret)
! 	return ret;
      }
  
    return exp;
  }
  
! /* Another variant, to build a new CALL_EXPR using the tail of the argument
!    list of EXP along with N new arguments.  */
  
! static tree
! rewrite_call_expr (tree exp, int skip, tree fn, int n, ...)
  {
!   tree arglist = CALL_EXPR_ARGS (exp);
!   int i;
!   for (i = 0; i < skip; i++)
!     arglist = TREE_CHAIN (arglist);
!   if (n > 0)
!     {
!       tree temp = NULL_TREE;
!       va_list ap;
!       va_start (ap, n);
!       for (i = 0; i < n; i++)
! 	{
! 	  tree arg = va_arg (ap, tree);
! 	  temp = tree_cons (NULL_TREE, arg, temp);
! 	}
!       va_end (ap);
!       for (i = 0; i < n; i++)  /* nreconc temp onto arglist */
! 	{
! 	  tree next = TREE_CHAIN (temp);
! 	  TREE_CHAIN (temp) = arglist;
! 	  arglist = temp;
! 	  temp = next;
! 	}
!     }
!   return build_function_call_expr (fn, arglist);
! }
! 
  
! /* Validate a single argument against a tree code representing a type. */
! 
! static int
! validate_arg (tree arg, enum tree_code code)
! {
!   if (!arg)
!     return 0;
!   else if (code == POINTER_TYPE)
!     return POINTER_TYPE_P (TREE_TYPE (arg));
!   else
!     return (code == TREE_CODE (TREE_TYPE (arg)));
  }
  
  /* This function validates the types of a function call argument list
!    against a specified list of tree_codes.  If the last specifier is a 0,
!    that represents an ellipses, otherwise the last specifier must be a
!    VOID_TYPE.  */
  
  static int
! validate_arglist (tree callexpr, ...)
  {
    enum tree_code code;
    int res = 0;
    va_list ap;
+   call_expr_arg_iterator iter;
+   tree arg;
  
!   va_start (ap, callexpr);
!   init_call_expr_arg_iterator (callexpr, &iter);
  
    do
      {
*************** validate_arglist (tree arglist, ...)
*** 8910,8933 ****
  	case VOID_TYPE:
  	  /* This signifies an endlink, if no arguments remain, return
  	     true, otherwise return false.  */
! 	  res = arglist == 0;
  	  goto end;
  	default:
  	  /* If no parameters remain or the parameter's code does not
  	     match the specified code, return false.  Otherwise continue
  	     checking any remaining arguments.  */
! 	  if (arglist == 0)
! 	    goto end;
! 	  if (code == POINTER_TYPE)
! 	    {
! 	      if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))))
! 		goto end;
! 	    }
! 	  else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
  	    goto end;
  	  break;
  	}
-       arglist = TREE_CHAIN (arglist);
      }
    while (1);
  
--- 9053,9069 ----
  	case VOID_TYPE:
  	  /* This signifies an endlink, if no arguments remain, return
  	     true, otherwise return false.  */
! 	  res = !more_call_expr_args_p (&iter);
  	  goto end;
  	default:
  	  /* If no parameters remain or the parameter's code does not
  	     match the specified code, return false.  Otherwise continue
  	     checking any remaining arguments.  */
! 	  arg = next_call_expr_arg (&iter);
! 	  if (!validate_arg (arg, code))
  	    goto end;
  	  break;
  	}
      }
    while (1);
  
*************** readonly_data_expr (tree exp)
*** 8995,9007 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strstr (tree arglist, tree type)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
        tree fn;
        const char *p1, *p2;
  
--- 9131,9142 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strstr (tree s1, tree s2, tree type)
  {
!   if (! (validate_arg (s1, POINTER_TYPE) && validate_arg (s2, POINTER_TYPE)))
      return 0;
    else
      {
        tree fn;
        const char *p1, *p2;
  
*************** fold_builtin_strstr (tree arglist, tree 
*** 9038,9047 ****
  
        /* New argument list transforming strstr(s1, s2) to
  	 strchr(s1, s2[0]).  */
!       arglist = build_tree_list (NULL_TREE,
! 				 build_int_cst (NULL_TREE, p2[0]));
!       arglist = tree_cons (NULL_TREE, s1, arglist);
!       return build_function_call_expr (fn, arglist);
      }
  }
  
--- 9173,9179 ----
  
        /* New argument list transforming strstr(s1, s2) to
  	 strchr(s1, s2[0]).  */
!       return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
      }
  }
  
*************** fold_builtin_strstr (tree arglist, tree 
*** 9063,9075 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strchr (tree arglist, tree type)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
        const char *p1;
  
        if (TREE_CODE (s2) != INTEGER_CST)
--- 9195,9206 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strchr (tree s1, tree s2, tree type)
  {
!   if (! (validate_arg (s1, POINTER_TYPE) && validate_arg (s2, INTEGER_TYPE)))
      return 0;
    else
      {
        const char *p1;
  
        if (TREE_CODE (s2) != INTEGER_CST)
*************** fold_builtin_strchr (tree arglist, tree 
*** 9117,9129 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strrchr (tree arglist, tree type)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
        tree fn;
        const char *p1;
  
--- 9248,9259 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strrchr (tree s1, tree s2, tree type)
  {
!   if (! (validate_arg (s1, POINTER_TYPE) && validate_arg (s2, INTEGER_TYPE)))
      return 0;
    else
      {
        tree fn;
        const char *p1;
  
*************** fold_builtin_strrchr (tree arglist, tree
*** 9159,9165 ****
  	return 0;
  
        /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
!       return build_function_call_expr (fn, arglist);
      }
  }
  
--- 9289,9295 ----
  	return 0;
  
        /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
!       return build_call_expr (fn, 2, s1, s2);
      }
  }
  
*************** fold_builtin_strrchr (tree arglist, tree
*** 9181,9193 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strpbrk (tree arglist, tree type)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
        tree fn;
        const char *p1, *p2;
  
--- 9311,9322 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strpbrk (tree s1, tree s2, tree type)
  {
!   if (! (validate_arg (s1, POINTER_TYPE) && validate_arg (s2, POINTER_TYPE)))
      return 0;
    else
      {
        tree fn;
        const char *p1, *p2;
  
*************** fold_builtin_strpbrk (tree arglist, tree
*** 9224,9233 ****
  
        /* New argument list transforming strpbrk(s1, s2) to
  	 strchr(s1, s2[0]).  */
!       arglist = build_tree_list (NULL_TREE,
! 				 build_int_cst (NULL_TREE, p2[0]));
!       arglist = tree_cons (NULL_TREE, s1, arglist);
!       return build_function_call_expr (fn, arglist);
      }
  }
  
--- 9353,9359 ----
  
        /* New argument list transforming strpbrk(s1, s2) to
  	 strchr(s1, s2[0]).  */
!       return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
      }
  }
  
*************** fold_builtin_strpbrk (tree arglist, tree
*** 9249,9262 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strcat (tree arglist)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree dst = TREE_VALUE (arglist),
- 	src = TREE_VALUE (TREE_CHAIN (arglist));
        const char *p = c_getstr (src);
  
        /* If the string length is zero, return the dst parameter.  */
--- 9375,9386 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strcat (tree dst, tree src)
  {
!   if (! (validate_arg (dst, POINTER_TYPE) && validate_arg (src, POINTER_TYPE)))
      return 0;
    else
      {
        const char *p = c_getstr (src);
  
        /* If the string length is zero, return the dst parameter.  */
*************** fold_builtin_strcat (tree arglist)
*** 9285,9300 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strncat (tree arglist)
  {
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree dst = TREE_VALUE (arglist);
-       tree src = TREE_VALUE (TREE_CHAIN (arglist));
-       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
        const char *p = c_getstr (src);
  
        /* If the requested length is zero, or the src parameter string
--- 9409,9422 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strncat (tree dst, tree src, tree len)
  {
!   if (! (validate_arg (dst, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)))
      return 0;
    else
      {
        const char *p = c_getstr (src);
  
        /* If the requested length is zero, or the src parameter string
*************** fold_builtin_strncat (tree arglist)
*** 9307,9314 ****
        if (TREE_CODE (len) == INTEGER_CST && p
  	  && compare_tree_int (len, strlen (p)) >= 0)
  	{
- 	  tree newarglist
- 	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
  	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
  
  	  /* If the replacement _DECL isn't initialized, don't do the
--- 9429,9434 ----
*************** fold_builtin_strncat (tree arglist)
*** 9316,9322 ****
  	  if (!fn)
  	    return 0;
  
! 	  return build_function_call_expr (fn, newarglist);
  	}
        return 0;
      }
--- 9436,9442 ----
  	  if (!fn)
  	    return 0;
  
! 	  return build_call_expr (fn, 2, dst, src);
  	}
        return 0;
      }
*************** fold_builtin_strncat (tree arglist)
*** 9340,9352 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strspn (tree arglist)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
        const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
  
        /* If both arguments are constants, evaluate at compile-time.  */
--- 9460,9471 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strspn (tree s1, tree s2)
  {
!   if (! (validate_arg (s1, POINTER_TYPE) && validate_arg (s2, POINTER_TYPE)))
      return 0;
    else
      {
        const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
  
        /* If both arguments are constants, evaluate at compile-time.  */
*************** fold_builtin_strspn (tree arglist)
*** 9384,9396 ****
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strcspn (tree arglist)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
    else
      {
-       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
        const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
  
        /* If both arguments are constants, evaluate at compile-time.  */
--- 9503,9514 ----
     form of the builtin function call.  */
  
  static tree
! fold_builtin_strcspn (tree s1, tree s2)
  {
!   if (! (validate_arg (s1, POINTER_TYPE) && validate_arg (s2, POINTER_TYPE)))
      return 0;
    else
      {
        const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
  
        /* If both arguments are constants, evaluate at compile-time.  */
*************** fold_builtin_strcspn (tree arglist)
*** 9412,9426 ****
        /* If the second argument is "", return __builtin_strlen(s1).  */
        if (p2 && *p2 == '\0')
  	{
! 	  tree newarglist = build_tree_list (NULL_TREE, s1),
! 	    fn = implicit_built_in_decls[BUILT_IN_STRLEN];
  
  	  /* If the replacement _DECL isn't initialized, don't do the
  	     transformation.  */
  	  if (!fn)
  	    return 0;
  
! 	  return build_function_call_expr (fn, newarglist);
  	}
        return 0;
      }
--- 9530,9543 ----
        /* If the second argument is "", return __builtin_strlen(s1).  */
        if (p2 && *p2 == '\0')
  	{
! 	  tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
  
  	  /* If the replacement _DECL isn't initialized, don't do the
  	     transformation.  */
  	  if (!fn)
  	    return 0;
  
! 	  return build_call_expr (fn, 1, s1);
  	}
        return 0;
      }
*************** fold_builtin_strcspn (tree arglist)
*** 9433,9441 ****
     was possible.  */
  
  tree
! fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
  {
-   tree fn;
    /* If we're using an unlocked function, assume the other unlocked
       functions exist explicitly.  */
    tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
--- 9550,9557 ----
     was possible.  */
  
  tree
! fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len)
  {
    /* If we're using an unlocked function, assume the other unlocked
       functions exist explicitly.  */
    tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
*************** fold_builtin_fputs (tree arglist, bool i
*** 9448,9458 ****
      return 0;
  
    /* Verify the arguments in the original call.  */
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      return 0;
  
    if (! len)
!     len = c_strlen (TREE_VALUE (arglist), 0);
  
    /* Get the length of the string passed to fputs.  If the length
       can't be determined, punt.  */
--- 9564,9575 ----
      return 0;
  
    /* Verify the arguments in the original call.  */
!   if (! (validate_arg (arg0, POINTER_TYPE)
! 	 && validate_arg (arg1, POINTER_TYPE)))
      return 0;
  
    if (! len)
!     len = c_strlen (arg0, 0);
  
    /* Get the length of the string passed to fputs.  If the length
       can't be determined, punt.  */
*************** fold_builtin_fputs (tree arglist, bool i
*** 9463,9556 ****
    switch (compare_tree_int (len, 1))
      {
      case -1: /* length is 0, delete the call entirely .  */
!       return omit_one_operand (integer_type_node, integer_zero_node,
! 			       TREE_VALUE (TREE_CHAIN (arglist)));
  
      case 0: /* length is 1, call fputc.  */
        {
! 	const char *p = c_getstr (TREE_VALUE (arglist));
  
  	if (p != NULL)
  	  {
  	    /* New argument list transforming fputs(string, stream) to
  	       fputc(string[0], stream).  */
! 	    arglist = build_tree_list (NULL_TREE,
! 				       TREE_VALUE (TREE_CHAIN (arglist)));
! 	    arglist = tree_cons (NULL_TREE,
! 				 build_int_cst (NULL_TREE, p[0]),
! 				 arglist);
! 	    fn = fn_fputc;
! 	    break;
  	  }
        }
        /* FALLTHROUGH */
      case 1: /* length is greater than 1, call fwrite.  */
        {
- 	tree string_arg;
- 
  	/* If optimizing for size keep fputs.  */
  	if (optimize_size)
  	  return 0;
- 	string_arg = TREE_VALUE (arglist);
  	/* New argument list transforming fputs(string, stream) to
  	   fwrite(string, 1, len, stream).  */
! 	arglist = build_tree_list (NULL_TREE,
! 				   TREE_VALUE (TREE_CHAIN (arglist)));
! 	arglist = tree_cons (NULL_TREE, len, arglist);
! 	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
! 	arglist = tree_cons (NULL_TREE, string_arg, arglist);
! 	fn = fn_fwrite;
! 	break;
        }
      default:
        gcc_unreachable ();
      }
! 
!   /* If the replacement _DECL isn't initialized, don't do the
!      transformation.  */
!   if (!fn)
!     return 0;
! 
!   /* These optimizations are only performed when the result is ignored,
!      hence there's no need to cast the result to integer_type_node.  */
!   return build_function_call_expr (fn, arglist);
  }
  
! /* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
     produced.  False otherwise.  This is done so that we don't output the error
     or warning twice or three times.  */
  bool
! fold_builtin_next_arg (tree arglist)
  {
    tree fntype = TREE_TYPE (current_function_decl);
  
    if (!stdarg_p (fntype))
      {
        error ("%<va_start%> used in function with fixed args");
        return true;
      }
!   else if (!arglist)
      {
!       /* Evidently an out of date version of <stdarg.h>; can't validate
! 	 va_start's second argument, but can still work as intended.  */
!       warning (0, "%<__builtin_next_arg%> called without an argument");
!       return true;
      }
!   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
!      when we checked the arguments and if needed issued a warning.  */
!   else if (!TREE_CHAIN (arglist)
! 	   || !integer_zerop (TREE_VALUE (arglist))
! 	   || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
! 	   || TREE_CHAIN (TREE_CHAIN (arglist)))
      {
!       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
!       tree arg = TREE_VALUE (arglist);
! 
!       if (TREE_CHAIN (arglist))
  	{
! 	  error ("%<va_start%> used with too many arguments");
  	  return true;
  	}
  
        /* Strip off all nops for the sake of the comparison.  This
  	 is not quite the same as STRIP_NOPS.  It does more.
--- 9580,9670 ----
    switch (compare_tree_int (len, 1))
      {
      case -1: /* length is 0, delete the call entirely .  */
!       return omit_one_operand (integer_type_node, integer_zero_node, arg1);
  
      case 0: /* length is 1, call fputc.  */
        {
! 	const char *p = c_getstr (arg0);
  
  	if (p != NULL)
  	  {
  	    /* New argument list transforming fputs(string, stream) to
  	       fputc(string[0], stream).  */
! 	    if (fn_fputc)
! 	      return build_call_expr (fn_fputc, 2,
! 				      build_int_cst (NULL_TREE, p[0]), arg1);
! 	    else
! 	      return 0;
  	  }
        }
        /* FALLTHROUGH */
      case 1: /* length is greater than 1, call fwrite.  */
        {
  	/* If optimizing for size keep fputs.  */
  	if (optimize_size)
  	  return 0;
  	/* New argument list transforming fputs(string, stream) to
  	   fwrite(string, 1, len, stream).  */
! 	if (fn_fwrite)
! 	  return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1);
! 	else
! 	  return 0;
        }
      default:
        gcc_unreachable ();
      }
!   return 0;
  }
  
! 
! /* Fold the next_arg or va_start call EXP. Returns true if there was an error
     produced.  False otherwise.  This is done so that we don't output the error
     or warning twice or three times.  */
  bool
! fold_builtin_next_arg (tree exp, bool va_start_p)
  {
    tree fntype = TREE_TYPE (current_function_decl);
+   int nargs = call_expr_nargs (exp);
+   tree arg;
  
    if (!stdarg_p (fntype))
      {
        error ("%<va_start%> used in function with fixed args");
        return true;
      }
! 
!   if (va_start_p)
      {
!       if (va_start_p && (nargs != 2))
! 	{
! 	  error ("wrong number of arguments to function %<va_start%>");
! 	  return true;
! 	}
!       arg = CALL_EXPR_ARG1 (exp);
      }
!   else
      {
!       if (nargs == 0)
! 	{
! 	  /* Evidently an out of date version of <stdarg.h>; can't validate
! 	     va_start's second argument, but can still work as intended.  */
! 	  warning (0, "%<__builtin_next_arg%> called without an argument");
! 	  return true;
! 	}
!       else if (nargs > 1)
  	{
! 	  error ("wrong number of arguments to function %<__builtin_next_arg%>");
  	  return true;
  	}
+       arg = CALL_EXPR_ARG0 (exp);
+     }
+ 
+   /* We destructively modify the call to be __builtin_va_start (ap, 0)
+      or __builtin_next_arg (0) the first time we see it, after checking 
+      the arguments and if needed issuing a warning.  */
+   if (!integer_zerop (arg))
+     {
+       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
  
        /* Strip off all nops for the sake of the comparison.  This
  	 is not quite the same as STRIP_NOPS.  It does more.
*************** fold_builtin_next_arg (tree arglist)
*** 9575,9582 ****
  	 as otherwise we could warn even for correct code like:
  	 void foo (int i, ...)
  	 { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
!       TREE_VALUE (arglist) = integer_zero_node;
!       TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
      }
    return false;
  }
--- 9689,9698 ----
  	 as otherwise we could warn even for correct code like:
  	 void foo (int i, ...)
  	 { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
!       if (va_start_p)
! 	CALL_EXPR_ARG1 (exp) = integer_zero_node;
!       else
! 	CALL_EXPR_ARG0 (exp) = integer_zero_node;
      }
    return false;
  }
*************** fold_builtin_next_arg (tree arglist)
*** 9589,9610 ****
     the caller does not use the returned value of the function.  */
  
  static tree
! fold_builtin_sprintf (tree arglist, int ignored)
  {
!   tree call, retval, dest, fmt;
    const char *fmt_str = NULL;
  
    /* Verify the required arguments in the original call.  We deal with two
       types of sprintf() calls: 'sprintf (str, fmt)' and
       'sprintf (dest, "%s", orig)'.  */
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
!       && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
! 			    VOID_TYPE))
      return NULL_TREE;
- 
-   /* Get the destination string and the format specifier.  */
-   dest = TREE_VALUE (arglist);
-   fmt = TREE_VALUE (TREE_CHAIN (arglist));
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
--- 9705,9723 ----
     the caller does not use the returned value of the function.  */
  
  static tree
! fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored)
  {
!   tree call, retval;
    const char *fmt_str = NULL;
  
    /* Verify the required arguments in the original call.  We deal with two
       types of sprintf() calls: 'sprintf (str, fmt)' and
       'sprintf (dest, "%s", orig)'.  */
!   if (! (validate_arg (dest, POINTER_TYPE) &&
! 	 validate_arg (fmt, POINTER_TYPE)))
!     return NULL_TREE;
!   if (orig && ! validate_arg (orig, POINTER_TYPE))
      return NULL_TREE;
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
*************** fold_builtin_sprintf (tree arglist, int 
*** 9627,9635 ****
  
        /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
  	 'format' is known to contain no % formats.  */
!       arglist = build_tree_list (NULL_TREE, fmt);
!       arglist = tree_cons (NULL_TREE, dest, arglist);
!       call = build_function_call_expr (fn, arglist);
        if (!ignored)
  	retval = build_int_cst (NULL_TREE, strlen (fmt_str));
      }
--- 9740,9746 ----
  
        /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
  	 'format' is known to contain no % formats.  */
!       call = build_call_expr (fn, 2, dest, fmt);
        if (!ignored)
  	retval = build_int_cst (NULL_TREE, strlen (fmt_str));
      }
*************** fold_builtin_sprintf (tree arglist, int 
*** 9637,9659 ****
    /* If the format is "%s", use strcpy if the result isn't used.  */
    else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
      {
!       tree fn, orig;
        fn = implicit_built_in_decls[BUILT_IN_STRCPY];
  
        if (!fn)
  	return NULL_TREE;
  
        /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2).  */
-       orig = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-       arglist = build_tree_list (NULL_TREE, orig);
-       arglist = tree_cons (NULL_TREE, dest, arglist);
        if (!ignored)
  	{
  	  retval = c_strlen (orig, 1);
  	  if (!retval || TREE_CODE (retval) != INTEGER_CST)
  	    return NULL_TREE;
  	}
!       call = build_function_call_expr (fn, arglist);
      }
  
    if (call && retval)
--- 9748,9767 ----
    /* If the format is "%s", use strcpy if the result isn't used.  */
    else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
      {
!       tree fn;
        fn = implicit_built_in_decls[BUILT_IN_STRCPY];
  
        if (!fn)
  	return NULL_TREE;
  
        /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2).  */
        if (!ignored)
  	{
  	  retval = c_strlen (orig, 1);
  	  if (!retval || TREE_CODE (retval) != INTEGER_CST)
  	    return NULL_TREE;
  	}
!       call = build_call_expr (fn, 2, dest, orig);
      }
  
    if (call && retval)
*************** expand_builtin_object_size (tree exp)
*** 9675,9684 ****
    tree ost;
    int object_size_type;
    tree fndecl = get_callee_fndecl (exp);
-   tree arglist = TREE_OPERAND (exp, 1);
    location_t locus = EXPR_LOCATION (exp);
  
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
        error ("%Hfirst argument of %D must be a pointer, second integer constant",
  	     &locus, fndecl);
--- 9783,9791 ----
    tree ost;
    int object_size_type;
    tree fndecl = get_callee_fndecl (exp);
    location_t locus = EXPR_LOCATION (exp);
  
!   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
        error ("%Hfirst argument of %D must be a pointer, second integer constant",
  	     &locus, fndecl);
*************** expand_builtin_object_size (tree exp)
*** 9686,9692 ****
        return const0_rtx;
      }
  
!   ost = TREE_VALUE (TREE_CHAIN (arglist));
    STRIP_NOPS (ost);
  
    if (TREE_CODE (ost) != INTEGER_CST
--- 9793,9799 ----
        return const0_rtx;
      }
  
!   ost = CALL_EXPR_ARG1 (exp);
    STRIP_NOPS (ost);
  
    if (TREE_CODE (ost) != INTEGER_CST
*************** static rtx
*** 9714,9733 ****
  expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
  			   enum built_in_function fcode)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    tree dest, src, len, size;
  
!   if (!validate_arglist (arglist,
  			 POINTER_TYPE,
  			 fcode == BUILT_IN_MEMSET_CHK
  			 ? INTEGER_TYPE : POINTER_TYPE,
  			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
!   dest = TREE_VALUE (arglist);
!   src = TREE_VALUE (TREE_CHAIN (arglist));
!   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
!   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
  
    if (! host_integerp (size, 1))
      return 0;
--- 9821,9839 ----
  expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
  			   enum built_in_function fcode)
  {
    tree dest, src, len, size;
  
!   if (!validate_arglist (exp,
  			 POINTER_TYPE,
  			 fcode == BUILT_IN_MEMSET_CHK
  			 ? INTEGER_TYPE : POINTER_TYPE,
  			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
!   dest = CALL_EXPR_ARG0 (exp);
!   src = CALL_EXPR_ARG1 (exp);
!   len = CALL_EXPR_ARG2 (exp);
!   size = call_expr_arg (exp, 3);
  
    if (! host_integerp (size, 1))
      return 0;
*************** expand_builtin_memory_chk (tree exp, rtx
*** 9744,9753 ****
  	  return 0;
  	}
  
-       arglist = build_tree_list (NULL_TREE, len);
-       arglist = tree_cons (NULL_TREE, src, arglist);
-       arglist = tree_cons (NULL_TREE, dest, arglist);
- 
        fn = NULL_TREE;
        /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
  	 mem{cpy,pcpy,move,set} is available.  */
--- 9850,9855 ----
*************** expand_builtin_memory_chk (tree exp, rtx
*** 9772,9778 ****
        if (! fn)
  	return 0;
  
!       fn = build_function_call_expr (fn, arglist);
        if (TREE_CODE (fn) == CALL_EXPR)
  	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
        return expand_expr (fn, target, mode, EXPAND_NORMAL);
--- 9874,9880 ----
        if (! fn)
  	return 0;
  
!       fn = build_call_expr (fn, 3, dest, src, len);
        if (TREE_CODE (fn) == CALL_EXPR)
  	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
        return expand_expr (fn, target, mode, EXPAND_NORMAL);
*************** expand_builtin_memory_chk (tree exp, rtx
*** 9821,9827 ****
  	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
  	      if (!fn)
  		return 0;
! 	      fn = build_function_call_expr (fn, arglist);
  	      if (TREE_CODE (fn) == CALL_EXPR)
  		CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
  	      return expand_expr (fn, target, mode, EXPAND_NORMAL);
--- 9923,9929 ----
  	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
  	      if (!fn)
  		return 0;
! 	      fn = build_call_expr (fn, 4, dest, src, len, size);
  	      if (TREE_CODE (fn) == CALL_EXPR)
  		CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
  	      return expand_expr (fn, target, mode, EXPAND_NORMAL);
*************** expand_builtin_memory_chk (tree exp, rtx
*** 9836,9843 ****
  static void
  maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
  {
!   int arg_mask, is_strlen = 0;
!   tree arglist = TREE_OPERAND (exp, 1), a;
    tree len, size;
    location_t locus;
  
--- 9938,9944 ----
  static void
  maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
  {
!   int is_strlen = 0;
    tree len, size;
    location_t locus;
  
*************** maybe_emit_chk_warning (tree exp, enum b
*** 9848,9884 ****
      /* For __strcat_chk the warning will be emitted only if overflowing
         by at least strlen (dest) + 1 bytes.  */
      case BUILT_IN_STRCAT_CHK:
!       arg_mask = 6;
        is_strlen = 1;
        break;
      case BUILT_IN_STRNCPY_CHK:
!       arg_mask = 12;
        break;
      case BUILT_IN_SNPRINTF_CHK:
      case BUILT_IN_VSNPRINTF_CHK:
!       arg_mask = 10;
        break;
      default:
        gcc_unreachable ();
      }
  
-   len = NULL_TREE;
-   size = NULL_TREE;
-   for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1)
-     if (arg_mask & 1)
-       {
- 	if (len)
- 	  size = a;
- 	else
- 	  len = a;
-       }
- 
    if (!len || !size)
      return;
  
-   len = TREE_VALUE (len);
-   size = TREE_VALUE (size);
- 
    if (! host_integerp (size, 1) || integer_all_onesp (size))
      return;
  
--- 9949,9974 ----
      /* For __strcat_chk the warning will be emitted only if overflowing
         by at least strlen (dest) + 1 bytes.  */
      case BUILT_IN_STRCAT_CHK:
!       len = call_expr_arg (exp, 1);
!       size = call_expr_arg (exp, 2);
        is_strlen = 1;
        break;
      case BUILT_IN_STRNCPY_CHK:
!       len = call_expr_arg (exp, 2);
!       size = call_expr_arg (exp, 3);
        break;
      case BUILT_IN_SNPRINTF_CHK:
      case BUILT_IN_VSNPRINTF_CHK:
!       len = call_expr_arg (exp, 1);
!       size = call_expr_arg (exp, 3);
        break;
      default:
        gcc_unreachable ();
      }
  
    if (!len || !size)
      return;
  
    if (! host_integerp (size, 1) || integer_all_onesp (size))
      return;
  
*************** maybe_emit_chk_warning (tree exp, enum b
*** 9902,9928 ****
  static void
  maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
  {
-   tree arglist = TREE_OPERAND (exp, 1);
    tree dest, size, len, fmt, flag;
    const char *fmt_str;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
!     return;
!   dest = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
!     return;
!   flag = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
      return;
!   size = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
!     return;
!   fmt = TREE_VALUE (arglist);
!   arglist = TREE_CHAIN (arglist);
  
    if (! host_integerp (size, 1) || integer_all_onesp (size))
      return;
--- 9992,10009 ----
  static void
  maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
  {
    tree dest, size, len, fmt, flag;
    const char *fmt_str;
+   int nargs = call_expr_nargs (exp);
  
    /* Verify the required arguments in the original call.  */
!   
!   if (nargs < 4)
      return;
!   dest = CALL_EXPR_ARG0 (exp);
!   flag = CALL_EXPR_ARG1 (exp);
!   size = CALL_EXPR_ARG2 (exp);
!   fmt = call_expr_arg (exp, 3);
  
    if (! host_integerp (size, 1) || integer_all_onesp (size))
      return;
*************** maybe_emit_sprintf_chk_warning (tree exp
*** 9944,9952 ****
      {
        tree arg;
  
!       if (! arglist)
  	return;
!       arg = TREE_VALUE (arglist);
        if (! POINTER_TYPE_P (TREE_TYPE (arg)))
  	return;
  
--- 10025,10033 ----
      {
        tree arg;
  
!       if (nargs < 5)
  	return;
!       arg = call_expr_arg (exp, 4);
        if (! POINTER_TYPE_P (TREE_TYPE (arg)))
  	return;
  
*************** maybe_emit_sprintf_chk_warning (tree exp
*** 9968,9983 ****
  /* Fold a call to __builtin_object_size, if possible.  */
  
  tree
! fold_builtin_object_size (tree arglist)
  {
!   tree ptr, ost, ret = 0;
    int object_size_type;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   ptr = TREE_VALUE (arglist);
-   ost = TREE_VALUE (TREE_CHAIN (arglist));
    STRIP_NOPS (ost);
  
    if (TREE_CODE (ost) != INTEGER_CST
--- 10049,10062 ----
  /* Fold a call to __builtin_object_size, if possible.  */
  
  tree
! fold_builtin_object_size (tree ptr, tree ost)
  {
!   tree ret = 0;
    int object_size_type;
  
!   if (! (validate_arg (ptr, POINTER_TYPE) && validate_arg (ost, INTEGER_TYPE)))
      return 0;
  
    STRIP_NOPS (ost);
  
    if (TREE_CODE (ost) != INTEGER_CST
*************** fold_builtin_object_size (tree arglist)
*** 10028,10051 ****
     passed as third argument.  */
  
  tree
! fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
  			 enum built_in_function fcode)
  {
!   tree dest, src, len, size, fn;
  
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE,
! 			 fcode == BUILT_IN_MEMSET_CHK
! 			 ? INTEGER_TYPE : POINTER_TYPE,
! 			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   /* Actually val for __memset_chk, but it doesn't matter.  */
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
- 
    /* If SRC and DEST are the same (and not volatile), return DEST
       (resp. DEST+LEN for __mempcpy_chk).  */
    if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
--- 10107,10127 ----
     passed as third argument.  */
  
  tree
! fold_builtin_memory_chk (tree fndecl,
! 			 tree dest, tree src, tree len, tree size,
! 			 tree maxlen, bool ignore,
  			 enum built_in_function fcode)
  {
!   tree fn;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src,
! 			  (fcode == BUILT_IN_MEMSET_CHK
! 			   ? INTEGER_TYPE : POINTER_TYPE))
! 	 && validate_arg (len, INTEGER_TYPE)
! 	 && validate_arg (size, INTEGER_TYPE)))
      return 0;
  
    /* If SRC and DEST are the same (and not volatile), return DEST
       (resp. DEST+LEN for __mempcpy_chk).  */
    if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
*************** fold_builtin_memory_chk (tree fndecl, tr
*** 10080,10086 ****
  		  if (!fn)
  		    return 0;
  
! 		  return build_function_call_expr (fn, arglist);
  		}
  	      return 0;
  	    }
--- 10156,10162 ----
  		  if (!fn)
  		    return 0;
  
! 		  return build_call_expr (fn, 4, dest, src, len, size);
  		}
  	      return 0;
  	    }
*************** fold_builtin_memory_chk (tree fndecl, tr
*** 10092,10101 ****
  	return 0;
      }
  
-   arglist = build_tree_list (NULL_TREE, len);
-   arglist = tree_cons (NULL_TREE, src, arglist);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    fn = NULL_TREE;
    /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
       mem{cpy,pcpy,move,set} is available.  */
--- 10168,10173 ----
*************** fold_builtin_memory_chk (tree fndecl, tr
*** 10120,10126 ****
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
  /* Fold a call to the __st[rp]cpy_chk builtin.
--- 10192,10198 ----
    if (!fn)
      return 0;
  
!   return build_call_expr (fn, 3, dest, src, len);
  }
  
  /* Fold a call to the __st[rp]cpy_chk builtin.
*************** fold_builtin_memory_chk (tree fndecl, tr
*** 10129,10147 ****
     strings passed as second argument.  */
  
  tree
! fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
  			 enum built_in_function fcode)
  {
!   tree dest, src, size, len, fn;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
! 			 VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    /* If SRC and DEST are the same (and not volatile), return DEST.  */
    if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
--- 10201,10217 ----
     strings passed as second argument.  */
  
  tree
! fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size,
! 			 tree maxlen, bool ignore,
  			 enum built_in_function fcode)
  {
!   tree len, fn;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (size, INTEGER_TYPE)))
      return 0;
  
    /* If SRC and DEST are the same (and not volatile), return DEST.  */
    if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
*************** fold_builtin_stxcpy_chk (tree fndecl, tr
*** 10170,10176 ****
  		  if (!fn)
  		    return 0;
  
! 		  return build_function_call_expr (fn, arglist);
  		}
  
  	      if (! len || TREE_SIDE_EFFECTS (len))
--- 10240,10246 ----
  		  if (!fn)
  		    return 0;
  
! 		  return build_call_expr (fn, 3, dest, src, size);
  		}
  
  	      if (! len || TREE_SIDE_EFFECTS (len))
*************** fold_builtin_stxcpy_chk (tree fndecl, tr
*** 10183,10194 ****
  		return 0;
  
  	      len = size_binop (PLUS_EXPR, len, ssize_int (1));
- 	      arglist = build_tree_list (NULL_TREE, size);
- 	      arglist = tree_cons (NULL_TREE, len, arglist);
- 	      arglist = tree_cons (NULL_TREE, src, arglist);
- 	      arglist = tree_cons (NULL_TREE, dest, arglist);
  	      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
! 				   build_function_call_expr (fn, arglist));
  	    }
  	}
        else
--- 10253,10261 ----
  		return 0;
  
  	      len = size_binop (PLUS_EXPR, len, ssize_int (1));
  	      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
! 				   build_call_expr (fn, 4,
! 						    dest, src, len, size));
  	    }
  	}
        else
*************** fold_builtin_stxcpy_chk (tree fndecl, tr
*** 10198,10232 ****
  	return 0;
      }
  
-   arglist = build_tree_list (NULL_TREE, src);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
    fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
  		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
  /* Fold a call to the __strncpy_chk builtin.
     If MAXLEN is not NULL, it is maximum length passed as third argument.  */
  
  tree
! fold_builtin_strncpy_chk (tree arglist, tree maxlen)
  {
!   tree dest, src, size, len, fn;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
! 			 INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
- 
    if (! host_integerp (size, 1))
      return 0;
  
--- 10265,10294 ----
  	return 0;
      }
  
    /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
    fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
  		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
    if (!fn)
      return 0;
  
!   return build_call_expr (fn, 2, dest, src);
  }
  
  /* Fold a call to the __strncpy_chk builtin.
     If MAXLEN is not NULL, it is maximum length passed as third argument.  */
  
  tree
! fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size,
! 			  tree maxlen)
  {
!   tree fn;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (len, INTEGER_TYPE)
! 	 && validate_arg (size, INTEGER_TYPE)))
      return 0;
  
    if (! host_integerp (size, 1))
      return 0;
  
*************** fold_builtin_strncpy_chk (tree arglist, 
*** 10247,10280 ****
  	return 0;
      }
  
-   arglist = build_tree_list (NULL_TREE, len);
-   arglist = tree_cons (NULL_TREE, src, arglist);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
    fn = built_in_decls[BUILT_IN_STRNCPY];
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
! /* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST.  */
  
  static tree
! fold_builtin_strcat_chk (tree fndecl, tree arglist)
  {
!   tree dest, src, size, fn;
    const char *p;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
! 			 VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 
    p = c_getstr (src);
    /* If the SRC parameter is "", return DEST.  */
    if (p && *p == '\0')
--- 10309,10335 ----
  	return 0;
      }
  
    /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
    fn = built_in_decls[BUILT_IN_STRNCPY];
    if (!fn)
      return 0;
  
!   return build_call_expr (fn, 3, dest, src, len);
  }
  
! /* Fold a call to the __strcat_chk builtin FNDECL */
  
  static tree
! fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size)
  {
!   tree fn;
    const char *p;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (size, INTEGER_TYPE)))
      return 0;
  
    p = c_getstr (src);
    /* If the SRC parameter is "", return DEST.  */
    if (p && *p == '\0')
*************** fold_builtin_strcat_chk (tree fndecl, tr
*** 10283,10316 ****
    if (! host_integerp (size, 1) || ! integer_all_onesp (size))
      return 0;
  
-   arglist = build_tree_list (NULL_TREE, src);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    /* If __builtin_strcat_chk is used, assume strcat is available.  */
    fn = built_in_decls[BUILT_IN_STRCAT];
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
  /* Fold a call to the __strncat_chk builtin EXP.  */
  
  static tree
! fold_builtin_strncat_chk (tree fndecl, tree arglist)
  {
!   tree dest, src, size, len, fn;
    const char *p;
  
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
! 			 INTEGER_TYPE, VOID_TYPE))
      return 0;
  
-   dest = TREE_VALUE (arglist);
-   src = TREE_VALUE (TREE_CHAIN (arglist));
-   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
- 
    p = c_getstr (src);
    /* If the SRC parameter is "" or if LEN is 0, return DEST.  */
    if (p && *p == '\0')
--- 10338,10366 ----
    if (! host_integerp (size, 1) || ! integer_all_onesp (size))
      return 0;
  
    /* If __builtin_strcat_chk is used, assume strcat is available.  */
    fn = built_in_decls[BUILT_IN_STRCAT];
    if (!fn)
      return 0;
  
!   return build_call_expr (fn, 2, dest, src);
  }
  
  /* Fold a call to the __strncat_chk builtin EXP.  */
  
  static tree
! fold_builtin_strncat_chk (tree fndecl,
! 			  tree dest, tree src, tree len, tree size)
  {
!   tree fn;
    const char *p;
  
!   if (! (validate_arg (dest, POINTER_TYPE)
! 	 && validate_arg (src, POINTER_TYPE)
! 	 && validate_arg (size, INTEGER_TYPE)
! 	 && validate_arg (size, INTEGER_TYPE)))
      return 0;
  
    p = c_getstr (src);
    /* If the SRC parameter is "" or if LEN is 0, return DEST.  */
    if (p && *p == '\0')
*************** fold_builtin_strncat_chk (tree fndecl, t
*** 10334,10394 ****
  	  if (!fn)
  	    return 0;
  
! 	  arglist = build_tree_list (NULL_TREE, size);
! 	  arglist = tree_cons (NULL_TREE, src, arglist);
! 	  arglist = tree_cons (NULL_TREE, dest, arglist);
! 	  return build_function_call_expr (fn, arglist);
  	}
        return 0;
      }
  
-   arglist = build_tree_list (NULL_TREE, len);
-   arglist = tree_cons (NULL_TREE, src, arglist);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    /* If __builtin_strncat_chk is used, assume strncat is available.  */
    fn = built_in_decls[BUILT_IN_STRNCAT];
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
! /* Fold a call to __{,v}sprintf_chk with argument list ARGLIST.  Return 0 if
     a normal call should be emitted rather than expanding the function
     inline.  FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK.  */
  
  static tree
! fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
  {
    tree dest, size, len, fn, fmt, flag;
    const char *fmt_str;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
!     return 0;
!   dest = TREE_VALUE (arglist);
!   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
      return 0;
!   flag = TREE_VALUE (arglist);
!   if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE)
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
      return 0;
!   size = TREE_VALUE (arglist);
!   if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
!     return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
!     return 0;
!   fmt = TREE_VALUE (arglist);
!   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
-   arglist = TREE_CHAIN (arglist);
  
    if (! host_integerp (size, 1))
      return 0;
--- 10384,10428 ----
  	  if (!fn)
  	    return 0;
  
! 	  return build_call_expr (fn, 3, dest, src, size);
  	}
        return 0;
      }
  
    /* If __builtin_strncat_chk is used, assume strncat is available.  */
    fn = built_in_decls[BUILT_IN_STRNCAT];
    if (!fn)
      return 0;
  
!   return build_call_expr (fn, 3, dest, src, len);
  }
  
! /* Fold a call EXP to __{,v}sprintf_chk.  Return 0 if
     a normal call should be emitted rather than expanding the function
     inline.  FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK.  */
  
  static tree
! fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode)
  {
    tree dest, size, len, fn, fmt, flag;
    const char *fmt_str;
+   int nargs = call_expr_nargs (exp);
  
    /* Verify the required arguments in the original call.  */
!   if (nargs < 4)
      return 0;
!   dest = CALL_EXPR_ARG0 (exp);
!   if (! validate_arg (dest, POINTER_TYPE))
      return 0;
!   flag = CALL_EXPR_ARG1 (exp);
!   if (! validate_arg (flag, INTEGER_TYPE))
      return 0;
!   size = CALL_EXPR_ARG2 (exp);
!   if (! validate_arg (size, INTEGER_TYPE))
      return 0;
!   fmt = call_expr_arg (exp, 3);
!   if (! validate_arg (fmt, POINTER_TYPE))
      return 0;
  
    if (! host_integerp (size, 1))
      return 0;
*************** fold_builtin_sprintf_chk (tree arglist, 
*** 10405,10423 ****
        /* If the format doesn't contain % args or %%, we know the size.  */
        if (strchr (fmt_str, target_percent) == 0)
  	{
! 	  if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
  	    len = build_int_cstu (size_type_node, strlen (fmt_str));
  	}
        /* If the format is "%s" and first ... argument is a string literal,
  	 we know the size too.  */
!       else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
  	{
  	  tree arg;
  
! 	  if (arglist && !TREE_CHAIN (arglist))
  	    {
! 	      arg = TREE_VALUE (arglist);
! 	      if (POINTER_TYPE_P (TREE_TYPE (arg)))
  		{
  		  len = c_strlen (arg, 1);
  		  if (! len || ! host_integerp (len, 1))
--- 10439,10458 ----
        /* If the format doesn't contain % args or %%, we know the size.  */
        if (strchr (fmt_str, target_percent) == 0)
  	{
! 	  if (fcode != BUILT_IN_SPRINTF_CHK || (nargs == 4))
  	    len = build_int_cstu (size_type_node, strlen (fmt_str));
  	}
        /* If the format is "%s" and first ... argument is a string literal,
  	 we know the size too.  */
!       else if (fcode == BUILT_IN_SPRINTF_CHK
! 	       && strcmp (fmt_str, target_percent_s) == 0)
  	{
  	  tree arg;
  
! 	  if (nargs == 5)
  	    {
! 	      arg = call_expr_arg (exp, 4);
! 	      if (validate_arg (arg, POINTER_TYPE))
  		{
  		  len = c_strlen (arg, 1);
  		  if (! len || ! host_integerp (len, 1))
*************** fold_builtin_sprintf_chk (tree arglist, 
*** 10439,10504 ****
      {
        if (fmt_str == NULL)
  	return 0;
!       if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
  	return 0;
      }
  
-   arglist = tree_cons (NULL_TREE, fmt, arglist);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
    fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
  		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
! /* Fold a call to {,v}snprintf with argument list ARGLIST.  Return 0 if
     a normal call should be emitted rather than expanding the function
     inline.  FCODE is either BUILT_IN_SNPRINTF_CHK or
     BUILT_IN_VSNPRINTF_CHK.  If MAXLEN is not NULL, it is maximum length
     passed as second argument.  */
  
  tree
! fold_builtin_snprintf_chk (tree arglist, tree maxlen,
  			   enum built_in_function fcode)
  {
    tree dest, size, len, fn, fmt, flag;
    const char *fmt_str;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
!     return 0;
!   dest = TREE_VALUE (arglist);
!   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
      return 0;
!   len = TREE_VALUE (arglist);
!   if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
      return 0;
!   flag = TREE_VALUE (arglist);
!   if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
      return 0;
!   arglist = TREE_CHAIN (arglist);
!   if (! arglist)
      return 0;
-   size = TREE_VALUE (arglist);
-   if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
-     return 0;
-   arglist = TREE_CHAIN (arglist);
-   if (! arglist)
-     return 0;
-   fmt = TREE_VALUE (arglist);
-   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
-     return 0;
-   arglist = TREE_CHAIN (arglist);
  
    if (! host_integerp (size, 1))
      return 0;
--- 10474,10524 ----
      {
        if (fmt_str == NULL)
  	return 0;
!       if (strchr (fmt_str, target_percent) != NULL
! 	  && strcmp (fmt_str, target_percent_s))
  	return 0;
      }
  
    /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
    fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
  		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
    if (!fn)
      return 0;
  
!   return rewrite_call_expr (exp, 4, fn, 2, dest, fmt);
  }
  
! /* Fold a call EXP to {,v}snprintf.  Return 0 if
     a normal call should be emitted rather than expanding the function
     inline.  FCODE is either BUILT_IN_SNPRINTF_CHK or
     BUILT_IN_VSNPRINTF_CHK.  If MAXLEN is not NULL, it is maximum length
     passed as second argument.  */
  
  tree
! fold_builtin_snprintf_chk (tree exp, tree maxlen,
  			   enum built_in_function fcode)
  {
    tree dest, size, len, fn, fmt, flag;
    const char *fmt_str;
  
    /* Verify the required arguments in the original call.  */
!   if (call_expr_nargs (exp) < 5)
      return 0;
!   dest = call_expr_arg (exp, 0);
!   if (! validate_arg (dest, POINTER_TYPE))
      return 0;
!   len = call_expr_arg (exp, 1);
!   if (! validate_arg (len, INTEGER_TYPE))
      return 0;
!   flag = call_expr_arg (exp, 2);
!   if (! validate_arg (flag, INTEGER_TYPE))
      return 0;
!   size = call_expr_arg (exp, 3);
!   if (! validate_arg (size, INTEGER_TYPE))
      return 0;
!   fmt = call_expr_arg (exp, 4);
!   if (! validate_arg (fmt, POINTER_TYPE))
      return 0;
  
    if (! host_integerp (size, 1))
      return 0;
*************** fold_builtin_snprintf_chk (tree arglist,
*** 10530,10543 ****
        fmt_str = c_getstr (fmt);
        if (fmt_str == NULL)
  	return 0;
!       if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
  	return 0;
      }
  
-   arglist = tree_cons (NULL_TREE, fmt, arglist);
-   arglist = tree_cons (NULL_TREE, len, arglist);
-   arglist = tree_cons (NULL_TREE, dest, arglist);
- 
    /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
       available.  */
    fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
--- 10550,10560 ----
        fmt_str = c_getstr (fmt);
        if (fmt_str == NULL)
  	return 0;
!       if (strchr (fmt_str, target_percent) != NULL
! 	  && strcmp (fmt_str, target_percent_s))
  	return 0;
      }
  
    /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
       available.  */
    fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
*************** fold_builtin_snprintf_chk (tree arglist,
*** 10545,10551 ****
    if (!fn)
      return 0;
  
!   return build_function_call_expr (fn, arglist);
  }
  
  /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
--- 10562,10568 ----
    if (!fn)
      return 0;
  
!   return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt);
  }
  
  /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
*************** fold_builtin_snprintf_chk (tree arglist,
*** 10555,10564 ****
     code of the function to be simplified.  */
  
  static tree
! fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
  		     enum built_in_function fcode)
  {
!   tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call;
    const char *fmt_str = NULL;
  
    /* If the return value is used, don't do the transformation.  */
--- 10572,10581 ----
     code of the function to be simplified.  */
  
  static tree
! fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore,
  		     enum built_in_function fcode)
  {
!   tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
    const char *fmt_str = NULL;
  
    /* If the return value is used, don't do the transformation.  */
*************** fold_builtin_printf (tree fndecl, tree a
*** 10566,10590 ****
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK)
!     {
!       tree flag;
! 
!       if (! arglist)
! 	return 0;
!       flag = TREE_VALUE (arglist);
!       if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
! 	  || TREE_SIDE_EFFECTS (flag))
! 	return 0;
!       arglist = TREE_CHAIN (arglist);
!     }
! 
!   if (! arglist)
!     return 0;
!   fmt = TREE_VALUE (arglist);
!   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
-   arglist = TREE_CHAIN (arglist);
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
--- 10583,10590 ----
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (! validate_arg (fmt, POINTER_TYPE))
      return 0;
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
*************** fold_builtin_printf (tree fndecl, tree a
*** 10616,10627 ****
  	  if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
  	    return 0;
  
! 	  if (! arglist
! 	      || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! 	      || TREE_CHAIN (arglist))
  	    return 0;
  
! 	  str = c_getstr (TREE_VALUE (arglist));
  	  if (str == NULL)
  	    return 0;
  	}
--- 10616,10625 ----
  	  if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
  	    return 0;
  
! 	  if (!arg || ! validate_arg (arg, POINTER_TYPE))
  	    return 0;
  
! 	  str = c_getstr (arg);
  	  if (str == NULL)
  	    return 0;
  	}
*************** fold_builtin_printf (tree fndecl, tree a
*** 10629,10635 ****
  	{
  	  /* The format specifier doesn't contain any '%' characters.  */
  	  if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
! 	      && arglist)
  	    return 0;
  	  str = fmt_str;
  	}
--- 10627,10633 ----
  	{
  	  /* The format specifier doesn't contain any '%' characters.  */
  	  if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
! 	      && arg)
  	    return 0;
  	  str = fmt_str;
  	}
*************** fold_builtin_printf (tree fndecl, tree a
*** 10644,10652 ****
  	  /* Given printf("c"), (where c is any one character,)
  	     convert "c"[0] to an int and pass that to the replacement
  	     function.  */
! 	  arg = build_int_cst (NULL_TREE, str[0]);
! 	  arglist = build_tree_list (NULL_TREE, arg);
! 	  fn = fn_putchar;
  	}
        else
  	{
--- 10642,10650 ----
  	  /* Given printf("c"), (where c is any one character,)
  	     convert "c"[0] to an int and pass that to the replacement
  	     function.  */
! 	  newarg = build_int_cst (NULL_TREE, str[0]);
! 	  if (fn_putchar)
! 	    call = build_call_expr (fn_putchar, 1, newarg);
  	}
        else
  	{
*************** fold_builtin_printf (tree fndecl, tree a
*** 10660,10668 ****
  	      memcpy (newstr, str, len - 1);
  	      newstr[len - 1] = 0;
  
! 	      arg = build_string_literal (len, newstr);
! 	      arglist = build_tree_list (NULL_TREE, arg);
! 	      fn = fn_puts;
  	    }
  	  else
  	    /* We'd like to arrange to call fputs(string,stdout) here,
--- 10658,10666 ----
  	      memcpy (newstr, str, len - 1);
  	      newstr[len - 1] = 0;
  
! 	      newarg = build_string_literal (len, newstr);
! 	      if (fn_puts)
! 		call = build_call_expr (fn_puts, 1, newarg);
  	    }
  	  else
  	    /* We'd like to arrange to call fputs(string,stdout) here,
*************** fold_builtin_printf (tree fndecl, tree a
*** 10678,10704 ****
    /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
    else if (strcmp (fmt_str, target_percent_s_newline) == 0)
      {
!       if (! arglist
! 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       fn = fn_puts;
      }
  
    /* If the format specifier was "%c", call __builtin_putchar(arg).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if (! arglist
! 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       fn = fn_putchar;
      }
  
!   if (!fn)
      return 0;
  
-   call = build_function_call_expr (fn, arglist);
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
  }
  
--- 10676,10699 ----
    /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
    else if (strcmp (fmt_str, target_percent_s_newline) == 0)
      {
!       if (!arg || ! validate_arg (arg, POINTER_TYPE))
  	return 0;
!       if (fn_puts)
! 	call = build_call_expr (fn_puts, 1, arg);
      }
  
    /* If the format specifier was "%c", call __builtin_putchar(arg).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if (! arg || ! validate_arg (arg, INTEGER_TYPE))
  	return 0;
!       if (fn_putchar)
! 	call = build_call_expr (fn_putchar, 1, arg);
      }
  
!   if (!call)
      return 0;
  
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
  }
  
*************** fold_builtin_printf (tree fndecl, tree a
*** 10709,10718 ****
     code of the function to be simplified.  */
  
  static tree
! fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
  		      enum built_in_function fcode)
  {
!   tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call;
    const char *fmt_str = NULL;
  
    /* If the return value is used, don't do the transformation.  */
--- 10704,10713 ----
     code of the function to be simplified.  */
  
  static tree
! fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore,
  		      enum built_in_function fcode)
  {
!   tree fn_fputc, fn_fputs, call = NULL_TREE;
    const char *fmt_str = NULL;
  
    /* If the return value is used, don't do the transformation.  */
*************** fold_builtin_fprintf (tree fndecl, tree 
*** 10720,10751 ****
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (! arglist)
!     return 0;
!   fp = TREE_VALUE (arglist);
!   if (! POINTER_TYPE_P (TREE_TYPE (fp)))
!     return 0;
!   arglist = TREE_CHAIN (arglist);
! 
!   if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK)
!     {
!       tree flag;
! 
!       if (! arglist)
! 	return 0;
!       flag = TREE_VALUE (arglist);
!       if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
! 	  || TREE_SIDE_EFFECTS (flag))
! 	return 0;
!       arglist = TREE_CHAIN (arglist);
!     }
! 
!   if (! arglist)
      return 0;
!   fmt = TREE_VALUE (arglist);
!   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
      return 0;
-   arglist = TREE_CHAIN (arglist);
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
--- 10715,10724 ----
      return 0;
  
    /* Verify the required arguments in the original call.  */
!   if (! validate_arg (fp, POINTER_TYPE))
      return 0;
!   if (! validate_arg (fmt, POINTER_TYPE))
      return 0;
  
    /* Check whether the format is a literal string constant.  */
    fmt_str = c_getstr (fmt);
*************** fold_builtin_fprintf (tree fndecl, tree 
*** 10772,10778 ****
    if (strchr (fmt_str, target_percent) == NULL)
      {
        if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
! 	  && arglist)
  	return 0;
  
        /* If the format specifier was "", fprintf does nothing.  */
--- 10745,10751 ----
    if (strchr (fmt_str, target_percent) == NULL)
      {
        if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
! 	  && arg)
  	return 0;
  
        /* If the format specifier was "", fprintf does nothing.  */
*************** fold_builtin_fprintf (tree fndecl, tree 
*** 10789,10797 ****
        /* When "string" doesn't contain %, replace all cases of
  	 fprintf (fp, string) with fputs (string, fp).  The fputs
  	 builtin will take care of special cases like length == 1.  */
!       arglist = build_tree_list (NULL_TREE, fp);
!       arglist = tree_cons (NULL_TREE, fmt, arglist);
!       fn = fn_fputs;
      }
  
    /* The other optimizations can be done only on the non-va_list variants.  */
--- 10762,10769 ----
        /* When "string" doesn't contain %, replace all cases of
  	 fprintf (fp, string) with fputs (string, fp).  The fputs
  	 builtin will take care of special cases like length == 1.  */
!       if (fn_fputs)
! 	call = build_call_expr (fn_fputs, 2, fmt, fp);
      }
  
    /* The other optimizations can be done only on the non-va_list variants.  */
*************** fold_builtin_fprintf (tree fndecl, tree 
*** 10801,10833 ****
    /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
    else if (strcmp (fmt_str, target_percent_s) == 0)
      {
!       if (! arglist
! 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       arg = TREE_VALUE (arglist);
!       arglist = build_tree_list (NULL_TREE, fp);
!       arglist = tree_cons (NULL_TREE, arg, arglist);
!       fn = fn_fputs;
      }
  
    /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if (! arglist
! 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
! 	  || TREE_CHAIN (arglist))
  	return 0;
!       arg = TREE_VALUE (arglist);
!       arglist = build_tree_list (NULL_TREE, fp);
!       arglist = tree_cons (NULL_TREE, arg, arglist);
!       fn = fn_fputc;
      }
  
!   if (!fn)
      return 0;
- 
-   call = build_function_call_expr (fn, arglist);
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
  }
  
--- 10773,10795 ----
    /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
    else if (strcmp (fmt_str, target_percent_s) == 0)
      {
!       if (!arg || ! validate_arg (arg, POINTER_TYPE))
  	return 0;
!       if (fn_fputs)
! 	call = build_call_expr (fn_fputs, 2, arg, fp);
      }
  
    /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
    else if (strcmp (fmt_str, target_percent_c) == 0)
      {
!       if (!arg || ! validate_arg (arg, INTEGER_TYPE))
  	return 0;
!       if (fn_fputc)
! 	call = build_call_expr (fn_fputc, 2, arg, fp);
      }
  
!   if (!call)
      return 0;
    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
  }
  
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c	(revision 115087)
--- gcc/fold-const.c	(working copy)
*************** fold_ternary (enum tree_code code, tree 
*** 11153,11163 ****
        return NULL_TREE;
  
      case CALL_EXPR:
!       /* Check for a built-in function.  */
!       if (TREE_CODE (op0) == ADDR_EXPR
! 	  && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL
! 	  && DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
! 	return fold_builtin (TREE_OPERAND (op0, 0), op1, false);
        return NULL_TREE;
  
      case BIT_FIELD_REF:
--- 11153,11159 ----
        return NULL_TREE;
  
      case CALL_EXPR:
!       /* Handled separately for now. */
        return NULL_TREE;
  
      case BIT_FIELD_REF:
*************** fold (tree expr)
*** 11221,11226 ****
--- 11217,11229 ----
        tree type = TREE_TYPE (t);
        tree op0, op1, op2;
  
+       /* CALL_EXPRs are special. */
+       if (code == CALL_EXPR)
+ 	{
+ 	  tem = fold_call_expr (expr, false);
+ 	  return tem ? tem : expr;
+ 	}
+ 
        switch (TREE_CODE_LENGTH (code))
  	{
  	case 1:
*************** fold_build3_stat (enum tree_code code, t
*** 11587,11596 ****
    md5_finish_ctx (&ctx, checksum_before_op2);
    htab_empty (ht);
  #endif
!   
!   tem = fold_ternary (code, type, op0, op1, op2);
!   if (!tem)
!     tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
        
  #ifdef ENABLE_FOLD_CHECKING
    md5_init_ctx (&ctx);
--- 11590,11608 ----
    md5_finish_ctx (&ctx, checksum_before_op2);
    htab_empty (ht);
  #endif
! 
!   /* This is only temporary, since CALL_EXPRs will have their own
!      low-level constructor once representation conversion is complete. */
!   if (code == CALL_EXPR)
!     {
!       tem = fold_build_call_expr (type, op0, op1, op2);
!     }
!   else
!     {
!       tem = fold_ternary (code, type, op0, op1, op2);
!       if (!tem)
! 	tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
!     }
        
  #ifdef ENABLE_FOLD_CHECKING
    md5_init_ctx (&ctx);
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c	(revision 115087)
--- gcc/tree-ssa-ccp.c	(working copy)
*************** ccp_fold (tree stmt)
*** 935,941 ****
        if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
  	{
  	  tree *orig, var;
- 	  tree fndecl, arglist;
  	  size_t i = 0;
  	  ssa_op_iter iter;
  	  use_operand_p var_p;
--- 935,940 ----
*************** ccp_fold (tree stmt)
*** 947,955 ****
  
  	  /* Substitute operands with their values and try to fold.  */
  	  replace_uses_in (stmt, NULL, const_val);
! 	  fndecl = get_callee_fndecl (rhs);
! 	  arglist = TREE_OPERAND (rhs, 1);
! 	  retval = fold_builtin (fndecl, arglist, false);
  
  	  /* Restore operands to their original form.  */
  	  i = 0;
--- 946,952 ----
  
  	  /* Substitute operands with their values and try to fold.  */
  	  replace_uses_in (stmt, NULL, const_val);
! 	  retval = fold_call_expr (rhs, false);
  
  	  /* Restore operands to their original form.  */
  	  i = 0;
*************** static tree
*** 2169,2186 ****
  ccp_fold_builtin (tree stmt, tree fn)
  {
    tree result, val[3];
!   tree callee, arglist, a;
    int arg_mask, i, type;
    bitmap visited;
    bool ignore;
  
    ignore = TREE_CODE (stmt) != MODIFY_EXPR;
  
    /* First try the generic builtin folder.  If that succeeds, return the
       result directly.  */
!   callee = get_callee_fndecl (fn);
!   arglist = TREE_OPERAND (fn, 1);
!   result = fold_builtin (callee, arglist, ignore);
    if (result)
      {
        if (ignore)
--- 2166,2183 ----
  ccp_fold_builtin (tree stmt, tree fn)
  {
    tree result, val[3];
!   tree callee, a;
    int arg_mask, i, type;
    bitmap visited;
    bool ignore;
+   call_expr_arg_iterator iter;
+   int nargs;
  
    ignore = TREE_CODE (stmt) != MODIFY_EXPR;
  
    /* First try the generic builtin folder.  If that succeeds, return the
       result directly.  */
!   result = fold_call_expr (fn, ignore);
    if (result)
      {
        if (ignore)
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2189,2200 ****
      }
  
    /* Ignore MD builtins.  */
    if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
      return NULL_TREE;
  
    /* If the builtin could not be folded, and it has no argument list,
       we're done.  */
!   if (!arglist)
      return NULL_TREE;
  
    /* Limit the work only for builtins we know how to simplify.  */
--- 2186,2199 ----
      }
  
    /* Ignore MD builtins.  */
+   callee = get_callee_fndecl (fn);
    if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
      return NULL_TREE;
  
    /* If the builtin could not be folded, and it has no argument list,
       we're done.  */
!   nargs = call_expr_nargs (fn);
!   if (nargs == 0)
      return NULL_TREE;
  
    /* Limit the work only for builtins we know how to simplify.  */
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2237,2251 ****
    visited = BITMAP_ALLOC (NULL);
  
    memset (val, 0, sizeof (val));
!   for (i = 0, a = arglist;
!        arg_mask;
!        i++, arg_mask >>= 1, a = TREE_CHAIN (a))
!     if (arg_mask & 1)
!       {
! 	bitmap_clear (visited);
! 	if (!get_maxval_strlen (TREE_VALUE (a), &val[i], visited, type))
! 	  val[i] = NULL_TREE;
!       }
  
    BITMAP_FREE (visited);
  
--- 2236,2252 ----
    visited = BITMAP_ALLOC (NULL);
  
    memset (val, 0, sizeof (val));
!   init_call_expr_arg_iterator (fn, &iter);
!   for (i = 0; arg_mask; i++, arg_mask >>= 1)
!     {
!       a = next_call_expr_arg (&iter);
!       if (arg_mask & 1)
! 	{
! 	  bitmap_clear (visited);
! 	  if (!get_maxval_strlen (a, &val[i], visited, type))
! 	    val[i] = NULL_TREE;
! 	}
!     }
  
    BITMAP_FREE (visited);
  
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2267,2289 ****
        break;
  
      case BUILT_IN_STRCPY:
!       if (val[1] && is_gimple_val (val[1]))
! 	result = fold_builtin_strcpy (callee, arglist, val[1]);
        break;
  
      case BUILT_IN_STRNCPY:
!       if (val[1] && is_gimple_val (val[1]))
! 	result = fold_builtin_strncpy (callee, arglist, val[1]);
        break;
  
      case BUILT_IN_FPUTS:
!       result = fold_builtin_fputs (arglist,
  				   TREE_CODE (stmt) != MODIFY_EXPR, 0,
  				   val[0]);
        break;
  
      case BUILT_IN_FPUTS_UNLOCKED:
!       result = fold_builtin_fputs (arglist,
  				   TREE_CODE (stmt) != MODIFY_EXPR, 1,
  				   val[0]);
        break;
--- 2268,2299 ----
        break;
  
      case BUILT_IN_STRCPY:
!       if (val[1] && is_gimple_val (val[1]) && nargs == 2)
! 	result = fold_builtin_strcpy (callee,
! 				      CALL_EXPR_ARG0 (fn),
! 				      CALL_EXPR_ARG1 (fn),
! 				      val[1]);
        break;
  
      case BUILT_IN_STRNCPY:
!       if (val[1] && is_gimple_val (val[1]) && nargs == 3)
! 	result = fold_builtin_strncpy (callee,
! 				       CALL_EXPR_ARG0 (fn),
! 				       CALL_EXPR_ARG1 (fn),
! 				       CALL_EXPR_ARG2 (fn),
! 				       val[1]);
        break;
  
      case BUILT_IN_FPUTS:
!       result = fold_builtin_fputs (CALL_EXPR_ARG0 (fn),
! 				   CALL_EXPR_ARG1 (fn),
  				   TREE_CODE (stmt) != MODIFY_EXPR, 0,
  				   val[0]);
        break;
  
      case BUILT_IN_FPUTS_UNLOCKED:
!       result = fold_builtin_fputs (CALL_EXPR_ARG0 (fn),
! 				   CALL_EXPR_ARG1 (fn),
  				   TREE_CODE (stmt) != MODIFY_EXPR, 1,
  				   val[0]);
        break;
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2293,2318 ****
      case BUILT_IN_MEMMOVE_CHK:
      case BUILT_IN_MEMSET_CHK:
        if (val[2] && is_gimple_val (val[2]))
! 	result = fold_builtin_memory_chk (callee, arglist, val[2], ignore,
  					  DECL_FUNCTION_CODE (callee));
        break;
  
      case BUILT_IN_STRCPY_CHK:
      case BUILT_IN_STPCPY_CHK:
        if (val[1] && is_gimple_val (val[1]))
! 	result = fold_builtin_stxcpy_chk (callee, arglist, val[1], ignore,
  					  DECL_FUNCTION_CODE (callee));
        break;
  
      case BUILT_IN_STRNCPY_CHK:
        if (val[2] && is_gimple_val (val[2]))
! 	result = fold_builtin_strncpy_chk (arglist, val[2]);
        break;
  
      case BUILT_IN_SNPRINTF_CHK:
      case BUILT_IN_VSNPRINTF_CHK:
        if (val[1] && is_gimple_val (val[1]))
! 	result = fold_builtin_snprintf_chk (arglist, val[1],
  					    DECL_FUNCTION_CODE (callee));
        break;
  
--- 2303,2341 ----
      case BUILT_IN_MEMMOVE_CHK:
      case BUILT_IN_MEMSET_CHK:
        if (val[2] && is_gimple_val (val[2]))
! 	result = fold_builtin_memory_chk (callee,
! 					  CALL_EXPR_ARG0 (fn),
! 					  CALL_EXPR_ARG1 (fn),
! 					  CALL_EXPR_ARG2 (fn),
! 					  call_expr_arg (fn, 3),
! 					  val[2], ignore,
  					  DECL_FUNCTION_CODE (callee));
        break;
  
      case BUILT_IN_STRCPY_CHK:
      case BUILT_IN_STPCPY_CHK:
        if (val[1] && is_gimple_val (val[1]))
! 	result = fold_builtin_stxcpy_chk (callee,
! 					  CALL_EXPR_ARG0 (fn),
! 					  CALL_EXPR_ARG1 (fn),
! 					  CALL_EXPR_ARG2 (fn),
! 					  val[1], ignore,
  					  DECL_FUNCTION_CODE (callee));
        break;
  
      case BUILT_IN_STRNCPY_CHK:
        if (val[2] && is_gimple_val (val[2]))
! 	result = fold_builtin_strncpy_chk (CALL_EXPR_ARG0 (fn),
! 					   CALL_EXPR_ARG1 (fn),
! 					   CALL_EXPR_ARG2 (fn),
! 					   call_expr_arg (fn, 3),
! 					   val[2]);
        break;
  
      case BUILT_IN_SNPRINTF_CHK:
      case BUILT_IN_VSNPRINTF_CHK:
        if (val[1] && is_gimple_val (val[1]))
! 	result = fold_builtin_snprintf_chk (fn, val[1],
  					    DECL_FUNCTION_CODE (callee));
        break;
  
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 115087)
--- gcc/gimplify.c	(working copy)
*************** gimplify_call_expr (tree *expr_p, tree *
*** 1987,1994 ****
    decl = get_callee_fndecl (*expr_p);
    if (decl && DECL_BUILT_IN (decl))
      {
!       tree arglist = TREE_OPERAND (*expr_p, 1);
!       tree new = fold_builtin (decl, arglist, !want_value);
  
        if (new && new != *expr_p)
  	{
--- 1987,1993 ----
    decl = get_callee_fndecl (*expr_p);
    if (decl && DECL_BUILT_IN (decl))
      {
!       tree new = fold_call_expr (*expr_p, !want_value);
  
        if (new && new != *expr_p)
  	{
*************** gimplify_call_expr (tree *expr_p, tree *
*** 2002,2022 ****
        if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
  	  && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START)
          {
! 	  if (!arglist || !TREE_CHAIN (arglist))
  	    {
  	      error ("too few arguments to function %<va_start%>");
  	      *expr_p = build_empty_stmt ();
  	      return GS_OK;
  	    }
  	  
! 	  if (fold_builtin_next_arg (TREE_CHAIN (arglist)))
  	    {
  	      *expr_p = build_empty_stmt ();
  	      return GS_OK;
  	    }
  	  /* Avoid gimplifying the second argument to va_start, which needs
  	     to be the plain PARM_DECL.  */
! 	  return gimplify_arg (&TREE_VALUE (TREE_OPERAND (*expr_p, 1)), pre_p);
  	}
      }
  
--- 2001,2021 ----
        if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
  	  && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START)
          {
! 	  if (call_expr_nargs (*expr_p) < 2)
  	    {
  	      error ("too few arguments to function %<va_start%>");
  	      *expr_p = build_empty_stmt ();
  	      return GS_OK;
  	    }
  	  
! 	  if (fold_builtin_next_arg (*expr_p, true))
  	    {
  	      *expr_p = build_empty_stmt ();
  	      return GS_OK;
  	    }
  	  /* Avoid gimplifying the second argument to va_start, which needs
  	     to be the plain PARM_DECL.  */
! 	  return gimplify_arg (&CALL_EXPR_ARG0 (*expr_p), pre_p);
  	}
      }
  
*************** gimplify_call_expr (tree *expr_p, tree *
*** 2044,2063 ****
    /* Try this again in case gimplification exposed something.  */
    if (ret != GS_ERROR)
      {
!       decl = get_callee_fndecl (*expr_p);
!       if (decl && DECL_BUILT_IN (decl))
! 	{
! 	  tree arglist = TREE_OPERAND (*expr_p, 1);
! 	  tree new = fold_builtin (decl, arglist, !want_value);
  
! 	  if (new && new != *expr_p)
! 	    {
! 	      /* There was a transformation of this call which computes the
! 		 same value, but in a more efficient way.  Return and try
! 		 again.  */
! 	      *expr_p = new;
! 	      return GS_OK;
! 	    }
  	}
      }
  
--- 2043,2057 ----
    /* Try this again in case gimplification exposed something.  */
    if (ret != GS_ERROR)
      {
!       tree new = fold_call_expr (*expr_p, !want_value);
  
!       if (new && new != *expr_p)
! 	{
! 	  /* There was a transformation of this call which computes the
! 	     same value, but in a more efficient way.  Return and try
! 	     again.  */
! 	  *expr_p = new;
! 	  return GS_OK;
  	}
      }
  
Index: gcc/except.c
===================================================================
*** gcc/except.c	(revision 115087)
--- gcc/except.c	(working copy)
*************** expand_builtin_unwind_init (void)
*** 2888,2896 ****
  }
  
  rtx
! expand_builtin_eh_return_data_regno (tree arglist)
  {
!   tree which = TREE_VALUE (arglist);
    unsigned HOST_WIDE_INT iwhich;
  
    if (TREE_CODE (which) != INTEGER_CST)
--- 2888,2896 ----
  }
  
  rtx
! expand_builtin_eh_return_data_regno (tree exp)
  {
!   tree which = CALL_EXPR_ARG0 (exp);
    unsigned HOST_WIDE_INT iwhich;
  
    if (TREE_CODE (which) != INTEGER_CST)
Index: gcc/tree-object-size.c
===================================================================
*** gcc/tree-object-size.c	(revision 115087)
--- gcc/tree-object-size.c	(working copy)
*************** compute_object_sizes (void)
*** 1005,1011 ****
  	    continue;
  
  	  init_object_sizes ();
! 	  result = fold_builtin (callee, TREE_OPERAND (call, 1), false);
  	  if (!result)
  	    {
  	      tree arglist = TREE_OPERAND (call, 1);
--- 1005,1011 ----
  	    continue;
  
  	  init_object_sizes ();
! 	  result = fold_call_expr (call, false);
  	  if (!result)
  	    {
  	      tree arglist = TREE_OPERAND (call, 1);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]