[patch] Split builtins.c

Jerry Quinn jlquinn@optonline.net
Sun Apr 25 20:47:00 GMT 2004


One of the beginner projects suggests splitting up big files, so I
took a crack at builtins.c.  I split off the fold_builtin_XX functions
into fold-builtin.c.  The main fallout was a few static functions that
had to be shared:

extern tree c_strlen (tree, int);
extern const char *c_getstr (tree);
extern enum type_class type_to_class (tree);

Bootstrapped i686-pc-gnu-linux.

2004-04-25  Jerry Quinn  <jlquinn@optonline.net>

        * Makefile.in (OBJS-common): Add fold-builtin.c.
	(fold-builtin.o): New.
	* fold-builtin.c (fold_builtin_constant_p,
	fold_builtin_classify_type, fold_builtin_inf,
	fold_builtin_nan, integer_valued_real_p,
	fold_trunc_transparent_mathfn, fold_builtin_cabs,
	fold_builtin_trunc, fold_builtin_floor, fold_builtin_ceil,
	fold_builtin_round, fold_builtin_bitop, fold_builtin_memcpy,
	fold_builtin_mempcpy, fold_builtin_memmove,
	fold_builtin_strcpy, fold_builtin_strncpy,
	fold_builtin_memcmp, fold_builtin_strcmp,
	fold_builtin_strncmp, fold_builtin_signbit, CASE_MATHFN,
	mathfn_built_in, builtin_mathfn_code, fold_builtin_logarithm,
	fold_builtin_exponent, fold_builtin_isascii,
	fold_builtin_toascii, fold_builtin_isdigit, fold_builtin):
	New, split from...
	* builtins.c: ...here.
	(c_strlen, c_getstr, type_to_class): Make extern.
	* tree.h: Fix up comment.


Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1272
diff -u -r1.1272 Makefile.in
--- Makefile.in	23 Apr 2004 22:50:06 -0000	1.1272
+++ Makefile.in	25 Apr 2004 17:54:33 -0000
@@ -852,7 +852,7 @@
  cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o 	   \
  dbxout.o debug.o df.o diagnostic.o dojump.o dominance.o loop-doloop.o	   \
  dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o		   \
- expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o		   \
+ expmed.o expr.o final.o flow.o fold-builtin.o fold-const.o function.o gcse.o		   \
  genrtl.o ggc-common.o global.o graph.o gtype-desc.o			   \
  haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o insn-modes.o	   \
  insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o	   \
@@ -1605,6 +1605,9 @@
    flags.h $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
    $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
    except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
+fold-builtin.o : fold-builtin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H)\
+   flags.h $(TARGET_H) function.h $(EXPR_H) insn-config.h \
+   typeclass.h toplev.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
 calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
    $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
    libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) cgraph.h except.h
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.314
diff -u -r1.314 builtins.c
--- builtins.c	23 Apr 2004 22:50:06 -0000	1.314
+++ builtins.c	25 Apr 2004 17:54:35 -0000
@@ -72,8 +72,8 @@
 tree implicit_built_in_decls[(int) END_BUILTINS];
 
 static int get_pointer_alignment (tree, unsigned int);
-static tree c_strlen (tree, int);
-static const char *c_getstr (tree);
+tree c_strlen (tree, int);
+const char *c_getstr (tree);
 static rtx c_readstr (const char *, enum machine_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree);
@@ -89,7 +89,7 @@
 static rtx expand_builtin_apply_args_1 (void);
 static rtx expand_builtin_apply (rtx, rtx, rtx);
 static void expand_builtin_return (rtx);
-static enum type_class type_to_class (tree);
+enum type_class type_to_class (tree);
 static rtx expand_builtin_classify_type (tree);
 static void expand_errno_check (tree, rtx);
 static rtx expand_builtin_mathfn (tree, rtx, rtx);
@@ -135,32 +135,11 @@
 static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
 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_classify_type (tree);
-static tree fold_builtin_inf (tree, int);
-static tree fold_builtin_nan (tree, tree, int);
 static int validate_arglist (tree, ...);
-static bool integer_valued_real_p (tree);
-static tree fold_trunc_transparent_mathfn (tree);
 static bool readonly_data_expr (tree);
 static rtx expand_builtin_fabs (tree, rtx, rtx);
 static rtx expand_builtin_cabs (tree, rtx);
 static rtx expand_builtin_signbit (tree, rtx);
-static tree fold_builtin_cabs (tree, tree);
-static tree fold_builtin_trunc (tree);
-static tree fold_builtin_floor (tree);
-static tree fold_builtin_ceil (tree);
-static tree fold_builtin_round (tree);
-static tree fold_builtin_bitop (tree);
-static tree fold_builtin_memcpy (tree);
-static tree fold_builtin_mempcpy (tree);
-static tree fold_builtin_memmove (tree);
-static tree fold_builtin_strcpy (tree);
-static tree fold_builtin_strncpy (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);
 
 /* Return the alignment in bits of EXP, a pointer valued expression.
    But don't return more than MAX_ALIGN no matter what.
@@ -246,7 +225,7 @@
    Unfortunately, string_constant can't access the values of const char
    arrays with initializers, so neither can we do so here.  */
 
-static tree
+tree
 c_strlen (tree src, int only_value)
 {
   tree offset_node;
@@ -327,7 +306,7 @@
 /* Return a char pointer for a C string if it is a string constant
    or sum of string constant and integer constant.  */
 
-static const char *
+const char *
 c_getstr (tree src)
 {
   tree offset_node;
@@ -1309,7 +1288,7 @@
 
 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
 
-static enum type_class
+enum type_class
 type_to_class (tree type)
 {
   switch (TREE_CODE (type))
@@ -1375,112 +1354,6 @@
   return tmp;
 }
 
-/* This helper macro, meant to be used in mathfn_built_in below,
-   determines which among a set of three builtin math functions is
-   appropriate for a given type mode.  The `F' and `L' cases are
-   automatically generated from the `double' case.  */
-#define CASE_MATHFN(BUILT_IN_MATHFN) \
-  case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
-  fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
-  fcodel = BUILT_IN_MATHFN##L ; break;
-
-/* Return mathematic function equivalent to FN but operating directly
-   on TYPE, if available.  If we can't do the conversion, return zero.  */
-tree
-mathfn_built_in (tree type, enum built_in_function fn)
-{
-  enum built_in_function fcode, fcodef, fcodel;
-
-  switch (fn)
-    {
-      CASE_MATHFN (BUILT_IN_ACOS)
-      CASE_MATHFN (BUILT_IN_ACOSH)
-      CASE_MATHFN (BUILT_IN_ASIN)
-      CASE_MATHFN (BUILT_IN_ASINH)
-      CASE_MATHFN (BUILT_IN_ATAN)
-      CASE_MATHFN (BUILT_IN_ATAN2)
-      CASE_MATHFN (BUILT_IN_ATANH)
-      CASE_MATHFN (BUILT_IN_CBRT)
-      CASE_MATHFN (BUILT_IN_CEIL)
-      CASE_MATHFN (BUILT_IN_COPYSIGN)
-      CASE_MATHFN (BUILT_IN_COS)
-      CASE_MATHFN (BUILT_IN_COSH)
-      CASE_MATHFN (BUILT_IN_DREM)
-      CASE_MATHFN (BUILT_IN_ERF)
-      CASE_MATHFN (BUILT_IN_ERFC)
-      CASE_MATHFN (BUILT_IN_EXP)
-      CASE_MATHFN (BUILT_IN_EXP10)
-      CASE_MATHFN (BUILT_IN_EXP2)
-      CASE_MATHFN (BUILT_IN_EXPM1)
-      CASE_MATHFN (BUILT_IN_FABS)
-      CASE_MATHFN (BUILT_IN_FDIM)
-      CASE_MATHFN (BUILT_IN_FLOOR)
-      CASE_MATHFN (BUILT_IN_FMA)
-      CASE_MATHFN (BUILT_IN_FMAX)
-      CASE_MATHFN (BUILT_IN_FMIN)
-      CASE_MATHFN (BUILT_IN_FMOD)
-      CASE_MATHFN (BUILT_IN_FREXP)
-      CASE_MATHFN (BUILT_IN_GAMMA)
-      CASE_MATHFN (BUILT_IN_HUGE_VAL)
-      CASE_MATHFN (BUILT_IN_HYPOT)
-      CASE_MATHFN (BUILT_IN_ILOGB)
-      CASE_MATHFN (BUILT_IN_INF)
-      CASE_MATHFN (BUILT_IN_J0)
-      CASE_MATHFN (BUILT_IN_J1)
-      CASE_MATHFN (BUILT_IN_JN)
-      CASE_MATHFN (BUILT_IN_LDEXP)
-      CASE_MATHFN (BUILT_IN_LGAMMA)
-      CASE_MATHFN (BUILT_IN_LLRINT)
-      CASE_MATHFN (BUILT_IN_LLROUND)
-      CASE_MATHFN (BUILT_IN_LOG)
-      CASE_MATHFN (BUILT_IN_LOG10)
-      CASE_MATHFN (BUILT_IN_LOG1P)
-      CASE_MATHFN (BUILT_IN_LOG2)
-      CASE_MATHFN (BUILT_IN_LOGB)
-      CASE_MATHFN (BUILT_IN_LRINT)
-      CASE_MATHFN (BUILT_IN_LROUND)
-      CASE_MATHFN (BUILT_IN_MODF)
-      CASE_MATHFN (BUILT_IN_NAN)
-      CASE_MATHFN (BUILT_IN_NANS)
-      CASE_MATHFN (BUILT_IN_NEARBYINT)
-      CASE_MATHFN (BUILT_IN_NEXTAFTER)
-      CASE_MATHFN (BUILT_IN_NEXTTOWARD)
-      CASE_MATHFN (BUILT_IN_POW)
-      CASE_MATHFN (BUILT_IN_POW10)
-      CASE_MATHFN (BUILT_IN_REMAINDER)
-      CASE_MATHFN (BUILT_IN_REMQUO)
-      CASE_MATHFN (BUILT_IN_RINT)
-      CASE_MATHFN (BUILT_IN_ROUND)
-      CASE_MATHFN (BUILT_IN_SCALB)
-      CASE_MATHFN (BUILT_IN_SCALBLN)
-      CASE_MATHFN (BUILT_IN_SCALBN)
-      CASE_MATHFN (BUILT_IN_SIGNIFICAND)
-      CASE_MATHFN (BUILT_IN_SIN)
-      CASE_MATHFN (BUILT_IN_SINCOS)
-      CASE_MATHFN (BUILT_IN_SINH)
-      CASE_MATHFN (BUILT_IN_SQRT)
-      CASE_MATHFN (BUILT_IN_TAN)
-      CASE_MATHFN (BUILT_IN_TANH)
-      CASE_MATHFN (BUILT_IN_TGAMMA)
-      CASE_MATHFN (BUILT_IN_TRUNC)
-      CASE_MATHFN (BUILT_IN_Y0)
-      CASE_MATHFN (BUILT_IN_Y1)
-      CASE_MATHFN (BUILT_IN_YN)
-
-      default:
-	return 0;
-      }
-
-  if (TYPE_MAIN_VARIANT (type) == double_type_node)
-    return implicit_built_in_decls[fcode];
-  else if (TYPE_MAIN_VARIANT (type) == float_type_node)
-    return implicit_built_in_decls[fcodef];
-  else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
-    return implicit_built_in_decls[fcodel];
-  else
-    return 0;
-}
-
 /* If errno must be maintained, expand the RTL to check if the result,
    TARGET, of a built-in function call, EXP, is NaN, and if so set
    errno to EDOM.  */
@@ -5739,601 +5612,6 @@
   return expand_call (exp, target, ignore);
 }
 
-/* Determine whether a tree node represents a call to a built-in
-   function.  If the tree T is a call to a built-in function with
-   the right number of arguments of the appropriate types, return
-   the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
-   Otherwise the return value is END_BUILTINS.  */
-
-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);
-  if (fndecl == NULL_TREE
-      || TREE_CODE (fndecl) != FUNCTION_DECL
-      || ! DECL_BUILT_IN (fndecl)
-      || 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,
-	 the last element in the list will have type `void'.  */
-      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))
-	{
-	  if (! SCALAR_FLOAT_TYPE_P (argtype))
-	    return END_BUILTINS;
-	}
-      else if (COMPLEX_FLOAT_TYPE_P (parmtype))
-	{
-	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
-	    return END_BUILTINS;
-	}
-      else if (POINTER_TYPE_P (parmtype))
-	{
-	  if (! POINTER_TYPE_P (argtype))
-	    return END_BUILTINS;
-	}
-      else if (INTEGRAL_TYPE_P (parmtype))
-	{
-	  if (! INTEGRAL_TYPE_P (argtype))
-	    return END_BUILTINS;
-	}
-      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 (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
-      || (TREE_CODE (arglist) == CONSTRUCTOR
-	  && TREE_CONSTANT (arglist))
-      || (TREE_CODE (arglist) == ADDR_EXPR
-	  && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
-    return integer_one_node;
-
-  /* If this expression has side effects, show we don't know it to be a
-     constant.  Likewise if it's a pointer or aggregate type since in
-     those case we only want literals, since those are only optimized
-     when generating RTL, not later.
-     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_classify_type.  */
-
-static tree
-fold_builtin_classify_type (tree arglist)
-{
-  if (arglist == 0)
-    return build_int_2 (no_type_class, 0);
-
-  return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
-}
-
-/* Fold a call to __builtin_inf or __builtin_huge_val.  */
-
-static tree
-fold_builtin_inf (tree type, int warn)
-{
-  REAL_VALUE_TYPE real;
-
-  if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
-    warning ("target format does not support infinity");
-
-  real_inf (&real);
-  return build_real (type, real);
-}
-
-/* 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;
-
-  if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
-    return 0;
-
-  return build_real (type, real);
-}
-
-/* Return true if the floating point expression T has an integer value.
-   We also allow +Inf, -Inf and NaN to be considered integer values.  */
-
-static bool
-integer_valued_real_p (tree t)
-{
-  switch (TREE_CODE (t))
-    {
-    case FLOAT_EXPR:
-      return true;
-
-    case ABS_EXPR:
-    case SAVE_EXPR:
-    case NON_LVALUE_EXPR:
-      return integer_valued_real_p (TREE_OPERAND (t, 0));
-
-    case COMPOUND_EXPR:
-    case MODIFY_EXPR:
-    case BIND_EXPR:
-      return integer_valued_real_p (TREE_OPERAND (t, 1));
-
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-    case MULT_EXPR:
-    case MIN_EXPR:
-    case MAX_EXPR:
-      return integer_valued_real_p (TREE_OPERAND (t, 0))
-	     && integer_valued_real_p (TREE_OPERAND (t, 1));
-
-    case COND_EXPR:
-      return integer_valued_real_p (TREE_OPERAND (t, 1))
-	     && integer_valued_real_p (TREE_OPERAND (t, 2));
-
-    case REAL_CST:
-      if (! TREE_CONSTANT_OVERFLOW (t))
-      {
-        REAL_VALUE_TYPE c, cint;
-
-	c = TREE_REAL_CST (t);
-	real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
-	return real_identical (&c, &cint);
-      }
-
-    case NOP_EXPR:
-      {
-	tree type = TREE_TYPE (TREE_OPERAND (t, 0));
-	if (TREE_CODE (type) == INTEGER_TYPE)
-	  return true;
-	if (TREE_CODE (type) == REAL_TYPE)
-	  return integer_valued_real_p (TREE_OPERAND (t, 0));
-	break;
-      }
-
-    case CALL_EXPR:
-      switch (builtin_mathfn_code (t))
-	{
-	case BUILT_IN_CEIL:
-	case BUILT_IN_CEILF:
-	case BUILT_IN_CEILL:
-	case BUILT_IN_FLOOR:
-	case BUILT_IN_FLOORF:
-	case BUILT_IN_FLOORL:
-	case BUILT_IN_NEARBYINT:
-	case BUILT_IN_NEARBYINTF:
-	case BUILT_IN_NEARBYINTL:
-	case BUILT_IN_RINT:
-	case BUILT_IN_RINTF:
-	case BUILT_IN_RINTL:
-	case BUILT_IN_ROUND:
-	case BUILT_IN_ROUNDF:
-	case BUILT_IN_ROUNDL:
-	case BUILT_IN_TRUNC:
-	case BUILT_IN_TRUNCF:
-	case BUILT_IN_TRUNCL:
-	  return true;
-
-	default:
-	  break;
-	}
-      break;
-
-    default:
-      break;
-    }
-  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 exp)
-{
-  tree fndecl = get_callee_fndecl (exp);
-  tree arglist = TREE_OPERAND (exp, 1);
-  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;
-
-  /* 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))
-    return arg;
-
-  if (optimize)
-    {
-      tree arg0 = strip_float_extensions (arg);
-      tree ftype = TREE_TYPE (exp);
-      tree newtype = TREE_TYPE (arg0);
-      tree decl;
-
-      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;
-}
-
-/* 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;
-
-  /* Evaluate cabs of a constant at compile-time.  */
-  if (flag_unsafe_math_optimizations
-      && TREE_CODE (arg) == COMPLEX_CST
-      && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
-      && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
-      && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
-      && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
-    {
-      REAL_VALUE_TYPE r, i;
-
-      r = TREE_REAL_CST (TREE_REALPART (arg));
-      i = TREE_REAL_CST (TREE_IMAGPART (arg));
-
-      real_arithmetic (&r, MULT_EXPR, &r, &r);
-      real_arithmetic (&i, MULT_EXPR, &i, &i);
-      real_arithmetic (&r, PLUS_EXPR, &r, &i);
-      if (real_sqrt (&r, TYPE_MODE (type), &r)
-	  || ! flag_trapping_math)
-	return build_real (type, r);
-    }
-
-  /* If either part is zero, cabs is fabs of the other.  */
-  if (TREE_CODE (arg) == COMPLEX_EXPR
-      && real_zerop (TREE_OPERAND (arg, 0)))
-    return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)));
-  if (TREE_CODE (arg) == COMPLEX_EXPR
-      && real_zerop (TREE_OPERAND (arg, 1)))
-    return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)));
-
-  if (flag_unsafe_math_optimizations)
-    {
-      tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
-
-      if (sqrtfn != NULL_TREE)
-	{
-	  tree rpart, ipart, result, arglist;
-
-	  arg = save_expr (arg);
-
-	  rpart = fold (build1 (REALPART_EXPR, type, arg));
-	  ipart = fold (build1 (IMAGPART_EXPR, type, arg));
-
-	  rpart = save_expr (rpart);
-	  ipart = save_expr (ipart);
-
-	  result = fold (build (PLUS_EXPR, type,
-				fold (build (MULT_EXPR, type,
-					     rpart, rpart)),
-				fold (build (MULT_EXPR, type,
-					     ipart, ipart))));
-
-	  arglist = build_tree_list (NULL_TREE, result);
-	  return build_function_call_expr (sqrtfn, arglist);
-	}
-    }
-
-  return NULL_TREE;
-}
-
-/* Fold function call to builtin trunc, truncf or truncl.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_trunc (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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;
-      tree type = TREE_TYPE (exp);
-
-      x = TREE_REAL_CST (arg);
-      real_trunc (&r, TYPE_MODE (type), &x);
-      return build_real (type, r);
-    }
-
-  return fold_trunc_transparent_mathfn (exp);
-}
-
-/* Fold function call to builtin floor, floorf or floorl.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_floor (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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;
-
-      x = TREE_REAL_CST (arg);
-      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
-	{
-	  tree type = TREE_TYPE (exp);
-	  REAL_VALUE_TYPE r;
-
-	  real_floor (&r, TYPE_MODE (type), &x);
-	  return build_real (type, r);
-	}
-    }
-
-  return fold_trunc_transparent_mathfn (exp);
-}
-
-/* Fold function call to builtin ceil, ceilf or ceill.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_ceil (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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;
-
-      x = TREE_REAL_CST (arg);
-      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
-	{
-	  tree type = TREE_TYPE (exp);
-	  REAL_VALUE_TYPE r;
-
-	  real_ceil (&r, TYPE_MODE (type), &x);
-	  return build_real (type, r);
-	}
-    }
-
-  return fold_trunc_transparent_mathfn (exp);
-}
-
-/* Fold function call to builtin round, roundf or roundl.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_round (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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;
-
-      x = TREE_REAL_CST (arg);
-      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
-	{
-	  tree type = TREE_TYPE (exp);
-	  REAL_VALUE_TYPE r;
-
-	  real_round (&r, TYPE_MODE (type), &x);
-	  return build_real (type, r);
-	}
-    }
-
-  return fold_trunc_transparent_mathfn (exp);
-}
-
-/* Fold function call to builtin ffs, clz, ctz, popcount and parity
-   and their long and long long variants (i.e. ffsl and ffsll).
-   Return NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_bitop (tree exp)
-{
-  tree fndecl = get_callee_fndecl (exp);
-  tree arglist = TREE_OPERAND (exp, 1);
-  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;
-      unsigned HOST_WIDE_INT lo;
-      tree type, t;
-
-      type = TREE_TYPE (arg);
-      width = TYPE_PRECISION (type);
-      lo = TREE_INT_CST_LOW (arg);
-
-      /* Clear all the bits that are beyond the type's precision.  */
-      if (width > HOST_BITS_PER_WIDE_INT)
-	{
-	  hi = TREE_INT_CST_HIGH (arg);
-	  if (width < 2 * HOST_BITS_PER_WIDE_INT)
-	    hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
-	}
-      else
-	{
-	  hi = 0;
-	  if (width < HOST_BITS_PER_WIDE_INT)
-	    lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
-	}
-
-      switch (DECL_FUNCTION_CODE (fndecl))
-	{
-	case BUILT_IN_FFS:
-	case BUILT_IN_FFSL:
-	case BUILT_IN_FFSLL:
-	  if (lo != 0)
-	    result = exact_log2 (lo & -lo) + 1;
-	  else if (hi != 0)
-	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
-	  else
-	    result = 0;
-	  break;
-
-	case BUILT_IN_CLZ:
-	case BUILT_IN_CLZL:
-	case BUILT_IN_CLZLL:
-	  if (hi != 0)
-	    result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
-	  else if (lo != 0)
-	    result = width - floor_log2 (lo) - 1;
-	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
-	    result = width;
-	  break;
-
-	case BUILT_IN_CTZ:
-	case BUILT_IN_CTZL:
-	case BUILT_IN_CTZLL:
-	  if (lo != 0)
-	    result = exact_log2 (lo & -lo);
-	  else if (hi != 0)
-	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
-	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
-	    result = width;
-	  break;
-
-	case BUILT_IN_POPCOUNT:
-	case BUILT_IN_POPCOUNTL:
-	case BUILT_IN_POPCOUNTLL:
-	  result = 0;
-	  while (lo)
-	    result++, lo &= lo - 1;
-	  while (hi)
-	    result++, hi &= hi - 1;
-	  break;
-
-	case BUILT_IN_PARITY:
-	case BUILT_IN_PARITYL:
-	case BUILT_IN_PARITYLL:
-	  result = 0;
-	  while (lo)
-	    result++, lo &= lo - 1;
-	  while (hi)
-	    result++, hi &= hi - 1;
-	  result &= 1;
-	  break;
-
-	default:
-	  abort();
-	}
-
-      t = build_int_2 (result, 0);
-      TREE_TYPE (t) = TREE_TYPE (exp);
-      return t;
-    }
-
-  return NULL_TREE;
-}
-
 /* Return true if EXPR is the real constant contained in VALUE.  */
 
 static bool
@@ -6347,1047 +5625,6 @@
           || (TREE_CODE (expr) == COMPLEX_CST
               && real_dconstp (TREE_REALPART (expr), value)
               && real_zerop (TREE_IMAGPART (expr))));
-}
-
-/* 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 exp, const REAL_VALUE_TYPE *value)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-
-  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-    {
-      tree fndecl = get_callee_fndecl (exp);
-      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.  */
-      if (real_onep (arg))
-	return build_real (type, dconst0);
-
-      /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
-         exactly, then only do this if flag_unsafe_math_optimizations.  */
-      if (exact_real_truncate (TYPE_MODE (type), value)
-	  || flag_unsafe_math_optimizations)
-        {
-	  const REAL_VALUE_TYPE value_truncate =
-	    real_value_truncate (TYPE_MODE (type), *value);
-	  if (real_dconstp (arg, &value_truncate))
-	    return build_real (type, dconst1);
-	}
-
-      /* Special case, optimize logN(expN(x)) = x.  */
-      if (flag_unsafe_math_optimizations
-	  && ((value == &dconste
-	       && (fcode == BUILT_IN_EXP
-		   || fcode == BUILT_IN_EXPF
-		   || fcode == BUILT_IN_EXPL))
-	      || (value == &dconst2
-		  && (fcode == BUILT_IN_EXP2
-		      || 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
-         order to transform logN(x**exponent) into exponent*logN(x).  */
-      if (flag_unsafe_math_optimizations)
-        {
-	  tree exponent = 0, x = 0;
-
-	  switch (fcode)
-	  {
-	  case BUILT_IN_EXP:
-	  case BUILT_IN_EXPF:
-	  case BUILT_IN_EXPL:
-	    /* 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 BUILT_IN_EXP2:
-	  case BUILT_IN_EXP2F:
-	  case BUILT_IN_EXP2L:
-	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
-	    x = build_real (type, dconst2);
-	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
-	    break;
-	  case BUILT_IN_EXP10:
-	  case BUILT_IN_EXP10F:
-	  case BUILT_IN_EXP10L:
-	  case BUILT_IN_POW10:
-	  case BUILT_IN_POW10F:
-	  case BUILT_IN_POW10L:
-	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
-	    x = build_real (type, dconst10);
-	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
-	    break;
-	  case BUILT_IN_SQRT:
-	  case BUILT_IN_SQRTF:
-	  case BUILT_IN_SQRTL:
-	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
-	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
-	    exponent = build_real (type, dconsthalf);
-	    break;
-	  case BUILT_IN_CBRT:
-	  case BUILT_IN_CBRTF:
-	  case BUILT_IN_CBRTL:
-	    /* 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 BUILT_IN_POW:
-	  case BUILT_IN_POWF:
-	  case BUILT_IN_POWL:
-	    /* 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;
-	  }
-
-	  /* 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 (build (MULT_EXPR, type, exponent, logfn));
-	    }
-	}
-    }
-
-  return 0;
-}
-
-/* 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 exp, const REAL_VALUE_TYPE *value)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-
-  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-    {
-      tree fndecl = get_callee_fndecl (exp);
-      tree type = TREE_TYPE (TREE_TYPE (fndecl));
-      tree arg = TREE_VALUE (arglist);
-
-      /* Optimize exp*(0.0) = 1.0.  */
-      if (real_zerop (arg))
-	return build_real (type, dconst1);
-
-      /* Optimize expN(1.0) = N.  */
-      if (real_onep (arg))
-        {
-	  REAL_VALUE_TYPE cst;
-
-	  real_convert (&cst, TYPE_MODE (type), value);
-	  return build_real (type, cst);
-	}
-
-      /* Attempt to evaluate expN(integer) at compile-time.  */
-      if (flag_unsafe_math_optimizations
-	  && TREE_CODE (arg) == REAL_CST
-	  && ! TREE_CONSTANT_OVERFLOW (arg))
-        {
-	  REAL_VALUE_TYPE cint;
-	  REAL_VALUE_TYPE c;
-	  HOST_WIDE_INT n;
-
-	  c = TREE_REAL_CST (arg);
-	  n = real_to_integer (&c);
-	  real_from_integer (&cint, VOIDmode, n,
-			     n < 0 ? -1 : 0, 0);
-	  if (real_identical (&c, &cint))
-	    {
-	      REAL_VALUE_TYPE x;
-
-	      real_powi (&x, TYPE_MODE (type), value, n);
-	      return build_real (type, x);
-	    }
-	}
-
-      /* Optimize expN(logN(x)) = x.  */
-      if (flag_unsafe_math_optimizations)
-        {
-	  const enum built_in_function fcode = builtin_mathfn_code (arg);
-
-	  if ((value == &dconste
-	       && (fcode == BUILT_IN_LOG
-		   || fcode == BUILT_IN_LOGF
-		   || fcode == BUILT_IN_LOGL))
-	      || (value == &dconst2
-		  && (fcode == BUILT_IN_LOG2
-		      || fcode == BUILT_IN_LOG2F
-		      || fcode == BUILT_IN_LOG2L))
-	      || (value == &dconst10
-		  && (fcode == BUILT_IN_LOG10
-		      || fcode == BUILT_IN_LOG10F
-		      || fcode == BUILT_IN_LOG10L)))
-	    return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
-	}
-    }
-
-  return 0;
-}
-
-/* Fold function call to builtin memcpy.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_memcpy (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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 (exp), 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 (exp), dest, len);
-
-  return 0;
-}
-
-/* Fold function call to builtin mempcpy.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_mempcpy (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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 (exp), dest, src);
-
-  /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
-  if (operand_equal_p (src, dest, 0))
-    {
-      tree temp = fold_convert (TREE_TYPE (dest), len);
-      temp = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, temp));
-      return fold_convert (TREE_TYPE (exp), temp);
-    }
-
-  return 0;
-}
-
-/* Fold function call to builtin memmove.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_memmove (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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 (exp), 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 (exp), dest, len);
-
-  return 0;
-}
-
-/* Fold function call to builtin strcpy.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_strcpy (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  tree dest, src;
-
-  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 (exp), dest);
-
-  return 0;
-}
-
-/* Fold function call to builtin strncpy.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_strncpy (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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 (exp), dest, src);
-
-  return 0;
-}
-
-/* Fold function call to builtin memcmp.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_memcmp (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  tree arg1, arg2, len;
-
-  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))
-    {
-      tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
-      return omit_one_operand (TREE_TYPE (exp), temp, arg1);
-    }
-
-  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
-  if (operand_equal_p (arg1, arg2, 0))
-    return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
-
-  return 0;
-}
-
-/* Fold function call to builtin strcmp.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_strcmp (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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 fold_convert (TREE_TYPE (exp), integer_zero_node);
-
-  p1 = c_getstr (arg1);
-  p2 = c_getstr (arg2);
-
-  if (p1 && p2)
-    {
-      tree temp;
-      const int i = strcmp (p1, p2);
-      if (i < 0)
-	temp = integer_minus_one_node;
-      else if (i > 0)
-	temp = integer_one_node;
-      else
-	temp = integer_zero_node;
-      return fold_convert (TREE_TYPE (exp), temp);
-    }
-
-  return 0;
-}
-
-/* Fold function call to builtin strncmp.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_strncmp (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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))
-    {
-      tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
-      return omit_one_operand (TREE_TYPE (exp), temp, arg1);
-    }
-
-  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
-  if (operand_equal_p (arg1, arg2, 0))
-    return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
-
-  p1 = c_getstr (arg1);
-  p2 = c_getstr (arg2);
-
-  if (host_integerp (len, 1) && p1 && p2)
-    {
-      tree temp;
-      const int i = strncmp (p1, p2, tree_low_cst (len, 1));
-      if (i < 0)
-	temp = integer_minus_one_node;
-      else if (i > 0)
-	temp = integer_one_node;
-      else
-	temp = integer_zero_node;
-      return fold_convert (TREE_TYPE (exp), temp);
-    }
-
-  return 0;
-}
-
-/* Fold function call to builtin signbit, signbitf or signbitl.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_signbit (tree exp)
-{
-  tree arglist = TREE_OPERAND (exp, 1);
-  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))
-    {
-      REAL_VALUE_TYPE c;
-
-      c = TREE_REAL_CST (arg);
-      temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
-      return fold_convert (TREE_TYPE (exp), temp);
-    }
-
-  /* If ARG is non-negative, the result is always zero.  */
-  if (tree_expr_nonnegative_p (arg))
-    return omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg);
-
-  /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
-  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
-    return fold (build (LT_EXPR, TREE_TYPE (exp), arg,
-			build_real (TREE_TYPE (arg), dconst0)));
-
-  return NULL_TREE;
-}
-
-/* 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);
-      
-      return fold (build (EQ_EXPR, integer_type_node,
-			  build (BIT_AND_EXPR, integer_type_node, arg,
-				 build_int_2 (~ (unsigned HOST_WIDE_INT) 0x7f,
-					      ~ (HOST_WIDE_INT) 0)),
-			  integer_zero_node));
-    }
-}
-
-/* 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 (build (BIT_AND_EXPR, integer_type_node, arg,
-			  build_int_2 (0x7f, 0)));
-    }
-}
-
-/* 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.  */
-      tree arg = TREE_VALUE (arglist);
-      arg = fold_convert (unsigned_type_node, arg);
-      arg = build (MINUS_EXPR, unsigned_type_node, arg,
-		   fold_convert (unsigned_type_node,
-				 build_int_2 (TARGET_DIGIT0, 0)));
-      arg = build (LE_EXPR, integer_type_node, arg,
-		   fold_convert (unsigned_type_node, build_int_2 (9, 0)));
-      return fold (arg);
-    }
-}
-
-/* Used by constant folding to eliminate some builtin calls early.  EXP is
-   the CALL_EXPR of a call to a builtin function.  */
-
-tree
-fold_builtin (tree exp)
-{
-  tree fndecl = get_callee_fndecl (exp);
-  tree arglist = TREE_OPERAND (exp, 1);
-  tree type = TREE_TYPE (TREE_TYPE (fndecl));
-
-  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
-    return 0;
-
-  switch (DECL_FUNCTION_CODE (fndecl))
-    {
-    case BUILT_IN_CONSTANT_P:
-      return fold_builtin_constant_p (arglist);
-
-    case BUILT_IN_CLASSIFY_TYPE:
-      return fold_builtin_classify_type (arglist);
-
-    case BUILT_IN_STRLEN:
-      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
-	{
-	  tree len = c_strlen (TREE_VALUE (arglist), 0);
-	  if (len)
-	    {
-	      /* Convert from the internal "sizetype" type to "size_t".  */
-	      if (size_type_node)
-		len = fold_convert (size_type_node, len);
-	      return len;
-	    }
-	}
-      break;
-
-    case BUILT_IN_FABS:
-    case BUILT_IN_FABSF:
-    case BUILT_IN_FABSL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	return fold (build1 (ABS_EXPR, type, TREE_VALUE (arglist)));
-      break;
-
-    case BUILT_IN_CABS:
-    case BUILT_IN_CABSF:
-    case BUILT_IN_CABSL:
-      return fold_builtin_cabs (arglist, type);
-
-    case BUILT_IN_SQRT:
-    case BUILT_IN_SQRTF:
-    case BUILT_IN_SQRTL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	{
-	  enum built_in_function fcode;
-	  tree arg = TREE_VALUE (arglist);
-
-	  /* Optimize sqrt of constant value.  */
-	  if (TREE_CODE (arg) == REAL_CST
-	      && ! TREE_CONSTANT_OVERFLOW (arg))
-	    {
-	      REAL_VALUE_TYPE r, x;
-
-	      x = TREE_REAL_CST (arg);
-	      if (real_sqrt (&r, TYPE_MODE (type), &x)
-		  || (!flag_trapping_math && !flag_errno_math))
-		return build_real (type, r);
-	    }
-
-	  /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
-	  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 (build (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)).  */
-	  if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
-	    {
-	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
-	      
-	      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 =
-		    BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
-		  
-		  /* Adjust for the outer root.  */
-		  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 sqrt(pow(x,y)) = pow(x,y*0.5).  */
-	  if (flag_unsafe_math_optimizations
-	      && (fcode == BUILT_IN_POW
-		  || 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 = fold (build (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);
-	    }
-	}
-      break;
-
-    case BUILT_IN_CBRT:
-    case BUILT_IN_CBRTF:
-    case BUILT_IN_CBRTL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	{
-	  tree arg = TREE_VALUE (arglist);
-	  const enum built_in_function fcode = builtin_mathfn_code (arg);
-
-	  /* Optimize cbrt of constant value.  */
-	  if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
-	    return arg;
-
-	  /* Optimize cbrt(expN(x)) -> expN(x/3).  */
-	  if (flag_unsafe_math_optimizations && 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 (build (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).  */
-	  /* We don't optimize cbrt(cbrt(x)) -> pow(x,1/9) because if
-             x is negative pow will error but cbrt won't.  */
-	  if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode))
-	    {
-	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
-
-	      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);
-		}
-	      
-	    }
-	}
-      break;
-
-    case BUILT_IN_SIN:
-    case BUILT_IN_SINF:
-    case BUILT_IN_SINL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	{
-	  tree arg = TREE_VALUE (arglist);
-
-	  /* Optimize sin(0.0) = 0.0.  */
-	  if (real_zerop (arg))
-	    return arg;
-	}
-      break;
-
-    case BUILT_IN_COS:
-    case BUILT_IN_COSF:
-    case BUILT_IN_COSL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	{
-	  tree arg = TREE_VALUE (arglist);
-
-	  /* Optimize cos(0.0) = 1.0.  */
-	  if (real_zerop (arg))
-	    return build_real (type, dconst1);
-
-	  /* Optimize cos(-x) into cos(x).  */
-	  if (TREE_CODE (arg) == NEGATE_EXPR)
-	    {
-	      tree arglist = build_tree_list (NULL_TREE,
-					      TREE_OPERAND (arg, 0));
-	      return build_function_call_expr (fndecl, arglist);
-	    }
-	}
-      break;
-
-    case BUILT_IN_EXP:
-    case BUILT_IN_EXPF:
-    case BUILT_IN_EXPL:
-      return fold_builtin_exponent (exp, &dconste);
-    case BUILT_IN_EXP2:
-    case BUILT_IN_EXP2F:
-    case BUILT_IN_EXP2L:
-      return fold_builtin_exponent (exp, &dconst2);
-    case BUILT_IN_EXP10:
-    case BUILT_IN_EXP10F:
-    case BUILT_IN_EXP10L:
-    case BUILT_IN_POW10:
-    case BUILT_IN_POW10F:
-    case BUILT_IN_POW10L:
-      return fold_builtin_exponent (exp, &dconst10);
-    case BUILT_IN_LOG:
-    case BUILT_IN_LOGF:
-    case BUILT_IN_LOGL:
-      return fold_builtin_logarithm (exp, &dconste);
-      break;
-    case BUILT_IN_LOG2:
-    case BUILT_IN_LOG2F:
-    case BUILT_IN_LOG2L:
-      return fold_builtin_logarithm (exp, &dconst2);
-      break;
-    case BUILT_IN_LOG10:
-    case BUILT_IN_LOG10F:
-    case BUILT_IN_LOG10L:
-      return fold_builtin_logarithm (exp, &dconst10);
-      break;
-
-    case BUILT_IN_TAN:
-    case BUILT_IN_TANF:
-    case BUILT_IN_TANL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	{
-	  enum built_in_function fcode;
-	  tree arg = TREE_VALUE (arglist);
-
-	  /* Optimize tan(0.0) = 0.0.  */
-	  if (real_zerop (arg))
-	    return arg;
-
-	  /* Optimize tan(atan(x)) = x.  */
-	  fcode = builtin_mathfn_code (arg);
-	  if (flag_unsafe_math_optimizations
-	      && (fcode == BUILT_IN_ATAN
-		  || fcode == BUILT_IN_ATANF
-		  || fcode == BUILT_IN_ATANL))
-	    return TREE_VALUE (TREE_OPERAND (arg, 1));
-	}
-      break;
-
-    case BUILT_IN_ATAN:
-    case BUILT_IN_ATANF:
-    case BUILT_IN_ATANL:
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	{
-	  tree arg = TREE_VALUE (arglist);
-
-	  /* Optimize atan(0.0) = 0.0.  */
-	  if (real_zerop (arg))
-	    return arg;
-
-	  /* Optimize atan(1.0) = pi/4.  */
-	  if (real_onep (arg))
-	    {
-	      REAL_VALUE_TYPE cst;
-
-	      real_convert (&cst, TYPE_MODE (type), &dconstpi);
-	      SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
-	      return build_real (type, cst);
-	    }
-	}
-      break;
-
-    case BUILT_IN_POW:
-    case BUILT_IN_POWF:
-    case BUILT_IN_POWL:
-      if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
-	{
-	  enum built_in_function fcode;
-	  tree arg0 = TREE_VALUE (arglist);
-	  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-
-	  /* Optimize pow(1.0,y) = 1.0.  */
-	  if (real_onep (arg0))
-	    return omit_one_operand (type, build_real (type, dconst1), arg1);
-
-	  if (TREE_CODE (arg1) == REAL_CST
-	      && ! TREE_CONSTANT_OVERFLOW (arg1))
-	    {
-	      REAL_VALUE_TYPE c;
-	      c = TREE_REAL_CST (arg1);
-
-	      /* Optimize pow(x,0.0) = 1.0.  */
-	      if (REAL_VALUES_EQUAL (c, dconst0))
-		return omit_one_operand (type, build_real (type, dconst1),
-					 arg0);
-
-	      /* Optimize pow(x,1.0) = x.  */
-	      if (REAL_VALUES_EQUAL (c, dconst1))
-		return arg0;
-
-	      /* Optimize pow(x,-1.0) = 1.0/x.  */
-	      if (REAL_VALUES_EQUAL (c, dconstm1))
-		return fold (build (RDIV_EXPR, type,
-				    build_real (type, dconst1),
-				    arg0));
-
-	      /* Optimize pow(x,0.5) = sqrt(x).  */
-	      if (flag_unsafe_math_optimizations
-		  && REAL_VALUES_EQUAL (c, dconsthalf))
-		{
-		  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);
-		    }
-		}
-
-	      /* Attempt to evaluate pow at compile-time.  */
-	      if (TREE_CODE (arg0) == REAL_CST
-		  && ! TREE_CONSTANT_OVERFLOW (arg0))
-		{
-		  REAL_VALUE_TYPE cint;
-		  HOST_WIDE_INT n;
-
-		  n = real_to_integer (&c);
-		  real_from_integer (&cint, VOIDmode, n,
-				     n < 0 ? -1 : 0, 0);
-		  if (real_identical (&c, &cint))
-		    {
-		      REAL_VALUE_TYPE x;
-		      bool inexact;
-
-		      x = TREE_REAL_CST (arg0);
-		      inexact = real_powi (&x, TYPE_MODE (type), &x, n);
-		      if (flag_unsafe_math_optimizations || !inexact)
-			return build_real (type, x);
-		    }
-		}
-	    }
-
-	  /* Optimize pow(expN(x),y) = expN(x*y).  */
-	  fcode = builtin_mathfn_code (arg0);
-	  if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
-	    {
-	      tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
-	      tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
-	      arg = fold (build (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 (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode))
-	    {
-	      tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
-	      tree narg1 = fold (build (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(pow(x,y),z) = pow(x,y*z).  */
-	  if (flag_unsafe_math_optimizations
-	      && (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 (build (MULT_EXPR, type, arg01, arg1));
-	      arglist = tree_cons (NULL_TREE, arg00,
-				   build_tree_list (NULL_TREE, narg1));
-	      return build_function_call_expr (fndecl, arglist);
-	    }
-	}
-      break;
-
-    case BUILT_IN_INF:
-    case BUILT_IN_INFF:
-    case BUILT_IN_INFL:
-      return fold_builtin_inf (type, true);
-
-    case BUILT_IN_HUGE_VAL:
-    case BUILT_IN_HUGE_VALF:
-    case BUILT_IN_HUGE_VALL:
-      return fold_builtin_inf (type, false);
-
-    case BUILT_IN_NAN:
-    case BUILT_IN_NANF:
-    case BUILT_IN_NANL:
-      return fold_builtin_nan (arglist, type, true);
-
-    case BUILT_IN_NANS:
-    case BUILT_IN_NANSF:
-    case BUILT_IN_NANSL:
-      return fold_builtin_nan (arglist, type, false);
-
-    case BUILT_IN_FLOOR:
-    case BUILT_IN_FLOORF:
-    case BUILT_IN_FLOORL:
-      return fold_builtin_floor (exp);
-
-    case BUILT_IN_CEIL:
-    case BUILT_IN_CEILF:
-    case BUILT_IN_CEILL:
-      return fold_builtin_ceil (exp);
-
-    case BUILT_IN_TRUNC:
-    case BUILT_IN_TRUNCF:
-    case BUILT_IN_TRUNCL:
-      return fold_builtin_trunc (exp);
-
-    case BUILT_IN_ROUND:
-    case BUILT_IN_ROUNDF:
-    case BUILT_IN_ROUNDL:
-      return fold_builtin_round (exp);
-
-    case BUILT_IN_NEARBYINT:
-    case BUILT_IN_NEARBYINTF:
-    case BUILT_IN_NEARBYINTL:
-    case BUILT_IN_RINT:
-    case BUILT_IN_RINTF:
-    case BUILT_IN_RINTL:
-      return fold_trunc_transparent_mathfn (exp);
-
-    case BUILT_IN_FFS:
-    case BUILT_IN_FFSL:
-    case BUILT_IN_FFSLL:
-    case BUILT_IN_CLZ:
-    case BUILT_IN_CLZL:
-    case BUILT_IN_CLZLL:
-    case BUILT_IN_CTZ:
-    case BUILT_IN_CTZL:
-    case BUILT_IN_CTZLL:
-    case BUILT_IN_POPCOUNT:
-    case BUILT_IN_POPCOUNTL:
-    case BUILT_IN_POPCOUNTLL:
-    case BUILT_IN_PARITY:
-    case BUILT_IN_PARITYL:
-    case BUILT_IN_PARITYLL:
-      return fold_builtin_bitop (exp);
-
-    case BUILT_IN_MEMCPY:
-      return fold_builtin_memcpy (exp);
-
-    case BUILT_IN_MEMPCPY:
-      return fold_builtin_mempcpy (exp);
-
-    case BUILT_IN_MEMMOVE:
-      return fold_builtin_memmove (exp);
-
-    case BUILT_IN_STRCPY:
-      return fold_builtin_strcpy (exp);
-
-    case BUILT_IN_STRNCPY:
-      return fold_builtin_strncpy (exp);
-
-    case BUILT_IN_MEMCMP:
-      return fold_builtin_memcmp (exp);
-
-    case BUILT_IN_STRCMP:
-      return fold_builtin_strcmp (exp);
-
-    case BUILT_IN_STRNCMP:
-      return fold_builtin_strncmp (exp);
-
-    case BUILT_IN_SIGNBIT:
-    case BUILT_IN_SIGNBITF:
-    case BUILT_IN_SIGNBITL:
-      return fold_builtin_signbit (exp);
-
-    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);
-
-    default:
-      break;
-    }
-
-  return 0;
 }
 
 /* Conveniently construct a function call expression.  */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.490
diff -u -r1.490 tree.h
--- tree.h	23 Apr 2004 22:50:16 -0000	1.490
+++ tree.h	25 Apr 2004 17:54:36 -0000
@@ -2977,8 +2977,10 @@
 extern tree omit_one_operand (tree, tree, tree);
 extern tree invert_truthvalue (tree);
 
-/* In builtins.c */
+/* In fold-builtin.c */
 extern tree fold_builtin (tree);
+
+/* In builtins.c */
 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);
diff -u -N fold-builtin.c.old fold-builtin.c
--- fold-builtin.c.old	1969-12-31 19:00:00.000000000 -0500
+++ fold-builtin.c	2004-04-25 13:48:54.000000000 -0400
@@ -0,0 +1,1870 @@
+/* Expand builtin functions.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "machmode.h"
+#include "real.h"
+#include "rtl.h"
+#include "tree.h"
+#include "flags.h"
+#include "function.h"
+#include "insn-config.h"
+#include "expr.h"
+#include "typeclass.h"
+#include "toplev.h"
+#include "tm_p.h"
+#include "target.h"
+#include "langhooks.h"
+
+/* Declarations used when constructing the builtin implicitly in the compiler.
+   It may be NULL_TREE when this is invalid (for instance runtime is not
+   required to implement the function call in all cases.  */
+extern tree implicit_built_in_decls[(int) END_BUILTINS];
+
+extern tree c_strlen (tree, int);
+extern const char *c_getstr (tree);
+extern enum type_class type_to_class (tree);
+static int validate_arglist (tree, ...);
+static tree fold_builtin_cabs (tree, tree);
+static tree fold_builtin_trunc (tree);
+static tree fold_builtin_floor (tree);
+static tree fold_builtin_ceil (tree);
+static tree fold_builtin_round (tree);
+static tree fold_builtin_bitop (tree);
+static tree fold_builtin_memcpy (tree);
+static tree fold_builtin_mempcpy (tree);
+static tree fold_builtin_memmove (tree);
+static tree fold_builtin_strcpy (tree);
+static tree fold_builtin_strncpy (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);
+
+/* This helper macro, meant to be used in mathfn_built_in below,
+   determines which among a set of three builtin math functions is
+   appropriate for a given type mode.  The `F' and `L' cases are
+   automatically generated from the `double' case.  */
+#define CASE_MATHFN(BUILT_IN_MATHFN) \
+  case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
+  fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
+  fcodel = BUILT_IN_MATHFN##L ; break;
+
+/* Return mathematic function equivalent to FN but operating directly
+   on TYPE, if available.  If we can't do the conversion, return zero.  */
+tree
+mathfn_built_in (tree type, enum built_in_function fn)
+{
+  enum built_in_function fcode, fcodef, fcodel;
+
+  switch (fn)
+    {
+      CASE_MATHFN (BUILT_IN_ACOS)
+      CASE_MATHFN (BUILT_IN_ACOSH)
+      CASE_MATHFN (BUILT_IN_ASIN)
+      CASE_MATHFN (BUILT_IN_ASINH)
+      CASE_MATHFN (BUILT_IN_ATAN)
+      CASE_MATHFN (BUILT_IN_ATAN2)
+      CASE_MATHFN (BUILT_IN_ATANH)
+      CASE_MATHFN (BUILT_IN_CBRT)
+      CASE_MATHFN (BUILT_IN_CEIL)
+      CASE_MATHFN (BUILT_IN_COPYSIGN)
+      CASE_MATHFN (BUILT_IN_COS)
+      CASE_MATHFN (BUILT_IN_COSH)
+      CASE_MATHFN (BUILT_IN_DREM)
+      CASE_MATHFN (BUILT_IN_ERF)
+      CASE_MATHFN (BUILT_IN_ERFC)
+      CASE_MATHFN (BUILT_IN_EXP)
+      CASE_MATHFN (BUILT_IN_EXP10)
+      CASE_MATHFN (BUILT_IN_EXP2)
+      CASE_MATHFN (BUILT_IN_EXPM1)
+      CASE_MATHFN (BUILT_IN_FABS)
+      CASE_MATHFN (BUILT_IN_FDIM)
+      CASE_MATHFN (BUILT_IN_FLOOR)
+      CASE_MATHFN (BUILT_IN_FMA)
+      CASE_MATHFN (BUILT_IN_FMAX)
+      CASE_MATHFN (BUILT_IN_FMIN)
+      CASE_MATHFN (BUILT_IN_FMOD)
+      CASE_MATHFN (BUILT_IN_FREXP)
+      CASE_MATHFN (BUILT_IN_GAMMA)
+      CASE_MATHFN (BUILT_IN_HUGE_VAL)
+      CASE_MATHFN (BUILT_IN_HYPOT)
+      CASE_MATHFN (BUILT_IN_ILOGB)
+      CASE_MATHFN (BUILT_IN_INF)
+      CASE_MATHFN (BUILT_IN_J0)
+      CASE_MATHFN (BUILT_IN_J1)
+      CASE_MATHFN (BUILT_IN_JN)
+      CASE_MATHFN (BUILT_IN_LDEXP)
+      CASE_MATHFN (BUILT_IN_LGAMMA)
+      CASE_MATHFN (BUILT_IN_LLRINT)
+      CASE_MATHFN (BUILT_IN_LLROUND)
+      CASE_MATHFN (BUILT_IN_LOG)
+      CASE_MATHFN (BUILT_IN_LOG10)
+      CASE_MATHFN (BUILT_IN_LOG1P)
+      CASE_MATHFN (BUILT_IN_LOG2)
+      CASE_MATHFN (BUILT_IN_LOGB)
+      CASE_MATHFN (BUILT_IN_LRINT)
+      CASE_MATHFN (BUILT_IN_LROUND)
+      CASE_MATHFN (BUILT_IN_MODF)
+      CASE_MATHFN (BUILT_IN_NAN)
+      CASE_MATHFN (BUILT_IN_NANS)
+      CASE_MATHFN (BUILT_IN_NEARBYINT)
+      CASE_MATHFN (BUILT_IN_NEXTAFTER)
+      CASE_MATHFN (BUILT_IN_NEXTTOWARD)
+      CASE_MATHFN (BUILT_IN_POW)
+      CASE_MATHFN (BUILT_IN_POW10)
+      CASE_MATHFN (BUILT_IN_REMAINDER)
+      CASE_MATHFN (BUILT_IN_REMQUO)
+      CASE_MATHFN (BUILT_IN_RINT)
+      CASE_MATHFN (BUILT_IN_ROUND)
+      CASE_MATHFN (BUILT_IN_SCALB)
+      CASE_MATHFN (BUILT_IN_SCALBLN)
+      CASE_MATHFN (BUILT_IN_SCALBN)
+      CASE_MATHFN (BUILT_IN_SIGNIFICAND)
+      CASE_MATHFN (BUILT_IN_SIN)
+      CASE_MATHFN (BUILT_IN_SINCOS)
+      CASE_MATHFN (BUILT_IN_SINH)
+      CASE_MATHFN (BUILT_IN_SQRT)
+      CASE_MATHFN (BUILT_IN_TAN)
+      CASE_MATHFN (BUILT_IN_TANH)
+      CASE_MATHFN (BUILT_IN_TGAMMA)
+      CASE_MATHFN (BUILT_IN_TRUNC)
+      CASE_MATHFN (BUILT_IN_Y0)
+      CASE_MATHFN (BUILT_IN_Y1)
+      CASE_MATHFN (BUILT_IN_YN)
+
+      default:
+	return 0;
+      }
+
+  if (TYPE_MAIN_VARIANT (type) == double_type_node)
+    return implicit_built_in_decls[fcode];
+  else if (TYPE_MAIN_VARIANT (type) == float_type_node)
+    return implicit_built_in_decls[fcodef];
+  else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
+    return implicit_built_in_decls[fcodel];
+  else
+    return 0;
+}
+
+/* Determine whether a tree node represents a call to a built-in
+   function.  If the tree T is a call to a built-in function with
+   the right number of arguments of the appropriate types, return
+   the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
+   Otherwise the return value is END_BUILTINS.  */
+
+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);
+  if (fndecl == NULL_TREE
+      || TREE_CODE (fndecl) != FUNCTION_DECL
+      || ! DECL_BUILT_IN (fndecl)
+      || 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,
+	 the last element in the list will have type `void'.  */
+      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))
+	{
+	  if (! SCALAR_FLOAT_TYPE_P (argtype))
+	    return END_BUILTINS;
+	}
+      else if (COMPLEX_FLOAT_TYPE_P (parmtype))
+	{
+	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
+	    return END_BUILTINS;
+	}
+      else if (POINTER_TYPE_P (parmtype))
+	{
+	  if (! POINTER_TYPE_P (argtype))
+	    return END_BUILTINS;
+	}
+      else if (INTEGRAL_TYPE_P (parmtype))
+	{
+	  if (! INTEGRAL_TYPE_P (argtype))
+	    return END_BUILTINS;
+	}
+      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 (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
+      || (TREE_CODE (arglist) == CONSTRUCTOR
+	  && TREE_CONSTANT (arglist))
+      || (TREE_CODE (arglist) == ADDR_EXPR
+	  && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
+    return integer_one_node;
+
+  /* If this expression has side effects, show we don't know it to be a
+     constant.  Likewise if it's a pointer or aggregate type since in
+     those case we only want literals, since those are only optimized
+     when generating RTL, not later.
+     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_classify_type.  */
+
+static tree
+fold_builtin_classify_type (tree arglist)
+{
+  if (arglist == 0)
+    return build_int_2 (no_type_class, 0);
+
+  return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
+}
+
+/* Fold a call to __builtin_inf or __builtin_huge_val.  */
+
+static tree
+fold_builtin_inf (tree type, int warn)
+{
+  REAL_VALUE_TYPE real;
+
+  if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
+    warning ("target format does not support infinity");
+
+  real_inf (&real);
+  return build_real (type, real);
+}
+
+/* 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;
+
+  if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
+    return 0;
+
+  return build_real (type, real);
+}
+
+/* Return true if the floating point expression T has an integer value.
+   We also allow +Inf, -Inf and NaN to be considered integer values.  */
+
+static bool
+integer_valued_real_p (tree t)
+{
+  switch (TREE_CODE (t))
+    {
+    case FLOAT_EXPR:
+      return true;
+
+    case ABS_EXPR:
+    case SAVE_EXPR:
+    case NON_LVALUE_EXPR:
+      return integer_valued_real_p (TREE_OPERAND (t, 0));
+
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
+    case BIND_EXPR:
+      return integer_valued_real_p (TREE_OPERAND (t, 1));
+
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+      return integer_valued_real_p (TREE_OPERAND (t, 0))
+	     && integer_valued_real_p (TREE_OPERAND (t, 1));
+
+    case COND_EXPR:
+      return integer_valued_real_p (TREE_OPERAND (t, 1))
+	     && integer_valued_real_p (TREE_OPERAND (t, 2));
+
+    case REAL_CST:
+      if (! TREE_CONSTANT_OVERFLOW (t))
+      {
+        REAL_VALUE_TYPE c, cint;
+
+	c = TREE_REAL_CST (t);
+	real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
+	return real_identical (&c, &cint);
+      }
+
+    case NOP_EXPR:
+      {
+	tree type = TREE_TYPE (TREE_OPERAND (t, 0));
+	if (TREE_CODE (type) == INTEGER_TYPE)
+	  return true;
+	if (TREE_CODE (type) == REAL_TYPE)
+	  return integer_valued_real_p (TREE_OPERAND (t, 0));
+	break;
+      }
+
+    case CALL_EXPR:
+      switch (builtin_mathfn_code (t))
+	{
+	case BUILT_IN_CEIL:
+	case BUILT_IN_CEILF:
+	case BUILT_IN_CEILL:
+	case BUILT_IN_FLOOR:
+	case BUILT_IN_FLOORF:
+	case BUILT_IN_FLOORL:
+	case BUILT_IN_NEARBYINT:
+	case BUILT_IN_NEARBYINTF:
+	case BUILT_IN_NEARBYINTL:
+	case BUILT_IN_RINT:
+	case BUILT_IN_RINTF:
+	case BUILT_IN_RINTL:
+	case BUILT_IN_ROUND:
+	case BUILT_IN_ROUNDF:
+	case BUILT_IN_ROUNDL:
+	case BUILT_IN_TRUNC:
+	case BUILT_IN_TRUNCF:
+	case BUILT_IN_TRUNCL:
+	  return true;
+
+	default:
+	  break;
+	}
+      break;
+
+    default:
+      break;
+    }
+  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 exp)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  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;
+
+  /* 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))
+    return arg;
+
+  if (optimize)
+    {
+      tree arg0 = strip_float_extensions (arg);
+      tree ftype = TREE_TYPE (exp);
+      tree newtype = TREE_TYPE (arg0);
+      tree decl;
+
+      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;
+}
+
+/* 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;
+
+  /* Evaluate cabs of a constant at compile-time.  */
+  if (flag_unsafe_math_optimizations
+      && TREE_CODE (arg) == COMPLEX_CST
+      && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
+      && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
+      && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
+      && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
+    {
+      REAL_VALUE_TYPE r, i;
+
+      r = TREE_REAL_CST (TREE_REALPART (arg));
+      i = TREE_REAL_CST (TREE_IMAGPART (arg));
+
+      real_arithmetic (&r, MULT_EXPR, &r, &r);
+      real_arithmetic (&i, MULT_EXPR, &i, &i);
+      real_arithmetic (&r, PLUS_EXPR, &r, &i);
+      if (real_sqrt (&r, TYPE_MODE (type), &r)
+	  || ! flag_trapping_math)
+	return build_real (type, r);
+    }
+
+  /* If either part is zero, cabs is fabs of the other.  */
+  if (TREE_CODE (arg) == COMPLEX_EXPR
+      && real_zerop (TREE_OPERAND (arg, 0)))
+    return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)));
+  if (TREE_CODE (arg) == COMPLEX_EXPR
+      && real_zerop (TREE_OPERAND (arg, 1)))
+    return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)));
+
+  if (flag_unsafe_math_optimizations)
+    {
+      tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
+
+      if (sqrtfn != NULL_TREE)
+	{
+	  tree rpart, ipart, result, arglist;
+
+	  arg = save_expr (arg);
+
+	  rpart = fold (build1 (REALPART_EXPR, type, arg));
+	  ipart = fold (build1 (IMAGPART_EXPR, type, arg));
+
+	  rpart = save_expr (rpart);
+	  ipart = save_expr (ipart);
+
+	  result = fold (build (PLUS_EXPR, type,
+				fold (build (MULT_EXPR, type,
+					     rpart, rpart)),
+				fold (build (MULT_EXPR, type,
+					     ipart, ipart))));
+
+	  arglist = build_tree_list (NULL_TREE, result);
+	  return build_function_call_expr (sqrtfn, arglist);
+	}
+    }
+
+  return NULL_TREE;
+}
+
+/* Fold function call to builtin trunc, truncf or truncl.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_trunc (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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;
+      tree type = TREE_TYPE (exp);
+
+      x = TREE_REAL_CST (arg);
+      real_trunc (&r, TYPE_MODE (type), &x);
+      return build_real (type, r);
+    }
+
+  return fold_trunc_transparent_mathfn (exp);
+}
+
+/* Fold function call to builtin floor, floorf or floorl.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_floor (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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;
+
+      x = TREE_REAL_CST (arg);
+      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
+	{
+	  tree type = TREE_TYPE (exp);
+	  REAL_VALUE_TYPE r;
+
+	  real_floor (&r, TYPE_MODE (type), &x);
+	  return build_real (type, r);
+	}
+    }
+
+  return fold_trunc_transparent_mathfn (exp);
+}
+
+/* Fold function call to builtin ceil, ceilf or ceill.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_ceil (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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;
+
+      x = TREE_REAL_CST (arg);
+      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
+	{
+	  tree type = TREE_TYPE (exp);
+	  REAL_VALUE_TYPE r;
+
+	  real_ceil (&r, TYPE_MODE (type), &x);
+	  return build_real (type, r);
+	}
+    }
+
+  return fold_trunc_transparent_mathfn (exp);
+}
+
+/* Fold function call to builtin round, roundf or roundl.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_round (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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;
+
+      x = TREE_REAL_CST (arg);
+      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
+	{
+	  tree type = TREE_TYPE (exp);
+	  REAL_VALUE_TYPE r;
+
+	  real_round (&r, TYPE_MODE (type), &x);
+	  return build_real (type, r);
+	}
+    }
+
+  return fold_trunc_transparent_mathfn (exp);
+}
+
+/* Fold function call to builtin ffs, clz, ctz, popcount and parity
+   and their long and long long variants (i.e. ffsl and ffsll).
+   Return NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_bitop (tree exp)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  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;
+      unsigned HOST_WIDE_INT lo;
+      tree type, t;
+
+      type = TREE_TYPE (arg);
+      width = TYPE_PRECISION (type);
+      lo = TREE_INT_CST_LOW (arg);
+
+      /* Clear all the bits that are beyond the type's precision.  */
+      if (width > HOST_BITS_PER_WIDE_INT)
+	{
+	  hi = TREE_INT_CST_HIGH (arg);
+	  if (width < 2 * HOST_BITS_PER_WIDE_INT)
+	    hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
+	}
+      else
+	{
+	  hi = 0;
+	  if (width < HOST_BITS_PER_WIDE_INT)
+	    lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
+	}
+
+      switch (DECL_FUNCTION_CODE (fndecl))
+	{
+	case BUILT_IN_FFS:
+	case BUILT_IN_FFSL:
+	case BUILT_IN_FFSLL:
+	  if (lo != 0)
+	    result = exact_log2 (lo & -lo) + 1;
+	  else if (hi != 0)
+	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
+	  else
+	    result = 0;
+	  break;
+
+	case BUILT_IN_CLZ:
+	case BUILT_IN_CLZL:
+	case BUILT_IN_CLZLL:
+	  if (hi != 0)
+	    result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
+	  else if (lo != 0)
+	    result = width - floor_log2 (lo) - 1;
+	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
+	    result = width;
+	  break;
+
+	case BUILT_IN_CTZ:
+	case BUILT_IN_CTZL:
+	case BUILT_IN_CTZLL:
+	  if (lo != 0)
+	    result = exact_log2 (lo & -lo);
+	  else if (hi != 0)
+	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
+	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
+	    result = width;
+	  break;
+
+	case BUILT_IN_POPCOUNT:
+	case BUILT_IN_POPCOUNTL:
+	case BUILT_IN_POPCOUNTLL:
+	  result = 0;
+	  while (lo)
+	    result++, lo &= lo - 1;
+	  while (hi)
+	    result++, hi &= hi - 1;
+	  break;
+
+	case BUILT_IN_PARITY:
+	case BUILT_IN_PARITYL:
+	case BUILT_IN_PARITYLL:
+	  result = 0;
+	  while (lo)
+	    result++, lo &= lo - 1;
+	  while (hi)
+	    result++, hi &= hi - 1;
+	  result &= 1;
+	  break;
+
+	default:
+	  abort();
+	}
+
+      t = build_int_2 (result, 0);
+      TREE_TYPE (t) = TREE_TYPE (exp);
+      return t;
+    }
+
+  return NULL_TREE;
+}
+
+/* Return true if EXPR is the real constant contained in VALUE.  */
+
+static bool
+real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
+{
+  STRIP_NOPS (expr);
+
+  return ((TREE_CODE (expr) == REAL_CST
+           && ! TREE_CONSTANT_OVERFLOW (expr)
+           && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
+          || (TREE_CODE (expr) == COMPLEX_CST
+              && real_dconstp (TREE_REALPART (expr), value)
+              && real_zerop (TREE_IMAGPART (expr))));
+}
+
+/* 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 exp, const REAL_VALUE_TYPE *value)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+
+  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    {
+      tree fndecl = get_callee_fndecl (exp);
+      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.  */
+      if (real_onep (arg))
+	return build_real (type, dconst0);
+
+      /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
+         exactly, then only do this if flag_unsafe_math_optimizations.  */
+      if (exact_real_truncate (TYPE_MODE (type), value)
+	  || flag_unsafe_math_optimizations)
+        {
+	  const REAL_VALUE_TYPE value_truncate =
+	    real_value_truncate (TYPE_MODE (type), *value);
+	  if (real_dconstp (arg, &value_truncate))
+	    return build_real (type, dconst1);
+	}
+
+      /* Special case, optimize logN(expN(x)) = x.  */
+      if (flag_unsafe_math_optimizations
+	  && ((value == &dconste
+	       && (fcode == BUILT_IN_EXP
+		   || fcode == BUILT_IN_EXPF
+		   || fcode == BUILT_IN_EXPL))
+	      || (value == &dconst2
+		  && (fcode == BUILT_IN_EXP2
+		      || 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
+         order to transform logN(x**exponent) into exponent*logN(x).  */
+      if (flag_unsafe_math_optimizations)
+        {
+	  tree exponent = 0, x = 0;
+
+	  switch (fcode)
+	  {
+	  case BUILT_IN_EXP:
+	  case BUILT_IN_EXPF:
+	  case BUILT_IN_EXPL:
+	    /* 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 BUILT_IN_EXP2:
+	  case BUILT_IN_EXP2F:
+	  case BUILT_IN_EXP2L:
+	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
+	    x = build_real (type, dconst2);
+	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
+	    break;
+	  case BUILT_IN_EXP10:
+	  case BUILT_IN_EXP10F:
+	  case BUILT_IN_EXP10L:
+	  case BUILT_IN_POW10:
+	  case BUILT_IN_POW10F:
+	  case BUILT_IN_POW10L:
+	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
+	    x = build_real (type, dconst10);
+	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
+	    break;
+	  case BUILT_IN_SQRT:
+	  case BUILT_IN_SQRTF:
+	  case BUILT_IN_SQRTL:
+	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
+	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
+	    exponent = build_real (type, dconsthalf);
+	    break;
+	  case BUILT_IN_CBRT:
+	  case BUILT_IN_CBRTF:
+	  case BUILT_IN_CBRTL:
+	    /* 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 BUILT_IN_POW:
+	  case BUILT_IN_POWF:
+	  case BUILT_IN_POWL:
+	    /* 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;
+	  }
+
+	  /* 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 (build (MULT_EXPR, type, exponent, logfn));
+	    }
+	}
+    }
+
+  return 0;
+}
+
+/* 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 exp, const REAL_VALUE_TYPE *value)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+
+  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    {
+      tree fndecl = get_callee_fndecl (exp);
+      tree type = TREE_TYPE (TREE_TYPE (fndecl));
+      tree arg = TREE_VALUE (arglist);
+
+      /* Optimize exp*(0.0) = 1.0.  */
+      if (real_zerop (arg))
+	return build_real (type, dconst1);
+
+      /* Optimize expN(1.0) = N.  */
+      if (real_onep (arg))
+        {
+	  REAL_VALUE_TYPE cst;
+
+	  real_convert (&cst, TYPE_MODE (type), value);
+	  return build_real (type, cst);
+	}
+
+      /* Attempt to evaluate expN(integer) at compile-time.  */
+      if (flag_unsafe_math_optimizations
+	  && TREE_CODE (arg) == REAL_CST
+	  && ! TREE_CONSTANT_OVERFLOW (arg))
+        {
+	  REAL_VALUE_TYPE cint;
+	  REAL_VALUE_TYPE c;
+	  HOST_WIDE_INT n;
+
+	  c = TREE_REAL_CST (arg);
+	  n = real_to_integer (&c);
+	  real_from_integer (&cint, VOIDmode, n,
+			     n < 0 ? -1 : 0, 0);
+	  if (real_identical (&c, &cint))
+	    {
+	      REAL_VALUE_TYPE x;
+
+	      real_powi (&x, TYPE_MODE (type), value, n);
+	      return build_real (type, x);
+	    }
+	}
+
+      /* Optimize expN(logN(x)) = x.  */
+      if (flag_unsafe_math_optimizations)
+        {
+	  const enum built_in_function fcode = builtin_mathfn_code (arg);
+
+	  if ((value == &dconste
+	       && (fcode == BUILT_IN_LOG
+		   || fcode == BUILT_IN_LOGF
+		   || fcode == BUILT_IN_LOGL))
+	      || (value == &dconst2
+		  && (fcode == BUILT_IN_LOG2
+		      || fcode == BUILT_IN_LOG2F
+		      || fcode == BUILT_IN_LOG2L))
+	      || (value == &dconst10
+		  && (fcode == BUILT_IN_LOG10
+		      || fcode == BUILT_IN_LOG10F
+		      || fcode == BUILT_IN_LOG10L)))
+	    return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
+	}
+    }
+
+  return 0;
+}
+
+/* Fold function call to builtin memcpy.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_memcpy (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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 (exp), 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 (exp), dest, len);
+
+  return 0;
+}
+
+/* Fold function call to builtin mempcpy.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_mempcpy (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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 (exp), dest, src);
+
+  /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
+  if (operand_equal_p (src, dest, 0))
+    {
+      tree temp = fold_convert (TREE_TYPE (dest), len);
+      temp = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, temp));
+      return fold_convert (TREE_TYPE (exp), temp);
+    }
+
+  return 0;
+}
+
+/* Fold function call to builtin memmove.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_memmove (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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 (exp), 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 (exp), dest, len);
+
+  return 0;
+}
+
+/* Fold function call to builtin strcpy.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_strcpy (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree dest, src;
+
+  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 (exp), dest);
+
+  return 0;
+}
+
+/* Fold function call to builtin strncpy.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_strncpy (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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 (exp), dest, src);
+
+  return 0;
+}
+
+/* Fold function call to builtin memcmp.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_memcmp (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree arg1, arg2, len;
+
+  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))
+    {
+      tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
+      return omit_one_operand (TREE_TYPE (exp), temp, arg1);
+    }
+
+  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
+  if (operand_equal_p (arg1, arg2, 0))
+    return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
+
+  return 0;
+}
+
+/* Fold function call to builtin strcmp.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_strcmp (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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 fold_convert (TREE_TYPE (exp), integer_zero_node);
+
+  p1 = c_getstr (arg1);
+  p2 = c_getstr (arg2);
+
+  if (p1 && p2)
+    {
+      tree temp;
+      const int i = strcmp (p1, p2);
+      if (i < 0)
+	temp = integer_minus_one_node;
+      else if (i > 0)
+	temp = integer_one_node;
+      else
+	temp = integer_zero_node;
+      return fold_convert (TREE_TYPE (exp), temp);
+    }
+
+  return 0;
+}
+
+/* Fold function call to builtin strncmp.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_strncmp (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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))
+    {
+      tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
+      return omit_one_operand (TREE_TYPE (exp), temp, arg1);
+    }
+
+  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
+  if (operand_equal_p (arg1, arg2, 0))
+    return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
+
+  p1 = c_getstr (arg1);
+  p2 = c_getstr (arg2);
+
+  if (host_integerp (len, 1) && p1 && p2)
+    {
+      tree temp;
+      const int i = strncmp (p1, p2, tree_low_cst (len, 1));
+      if (i < 0)
+	temp = integer_minus_one_node;
+      else if (i > 0)
+	temp = integer_one_node;
+      else
+	temp = integer_zero_node;
+      return fold_convert (TREE_TYPE (exp), temp);
+    }
+
+  return 0;
+}
+
+/* Fold function call to builtin signbit, signbitf or signbitl.  Return
+   NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_signbit (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  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))
+    {
+      REAL_VALUE_TYPE c;
+
+      c = TREE_REAL_CST (arg);
+      temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
+      return fold_convert (TREE_TYPE (exp), temp);
+    }
+
+  /* If ARG is non-negative, the result is always zero.  */
+  if (tree_expr_nonnegative_p (arg))
+    return omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg);
+
+  /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
+  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
+    return fold (build (LT_EXPR, TREE_TYPE (exp), arg,
+			build_real (TREE_TYPE (arg), dconst0)));
+
+  return NULL_TREE;
+}
+
+/* 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);
+      
+      return fold (build (EQ_EXPR, integer_type_node,
+			  build (BIT_AND_EXPR, integer_type_node, arg,
+				 build_int_2 (~ (unsigned HOST_WIDE_INT) 0x7f,
+					      ~ (HOST_WIDE_INT) 0)),
+			  integer_zero_node));
+    }
+}
+
+/* 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 (build (BIT_AND_EXPR, integer_type_node, arg,
+			  build_int_2 (0x7f, 0)));
+    }
+}
+
+/* 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.  */
+      tree arg = TREE_VALUE (arglist);
+      arg = fold_convert (unsigned_type_node, arg);
+      arg = build (MINUS_EXPR, unsigned_type_node, arg,
+		   fold_convert (unsigned_type_node,
+				 build_int_2 (TARGET_DIGIT0, 0)));
+      arg = build (LE_EXPR, integer_type_node, arg,
+		   fold_convert (unsigned_type_node, build_int_2 (9, 0)));
+      return fold (arg);
+    }
+}
+
+/* Used by constant folding to eliminate some builtin calls early.  EXP is
+   the CALL_EXPR of a call to a builtin function.  */
+
+tree
+fold_builtin (tree exp)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree type = TREE_TYPE (TREE_TYPE (fndecl));
+
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+    return 0;
+
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_CONSTANT_P:
+      return fold_builtin_constant_p (arglist);
+
+    case BUILT_IN_CLASSIFY_TYPE:
+      return fold_builtin_classify_type (arglist);
+
+    case BUILT_IN_STRLEN:
+      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+	{
+	  tree len = c_strlen (TREE_VALUE (arglist), 0);
+	  if (len)
+	    {
+	      /* Convert from the internal "sizetype" type to "size_t".  */
+	      if (size_type_node)
+		len = fold_convert (size_type_node, len);
+	      return len;
+	    }
+	}
+      break;
+
+    case BUILT_IN_FABS:
+    case BUILT_IN_FABSF:
+    case BUILT_IN_FABSL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	return fold (build1 (ABS_EXPR, type, TREE_VALUE (arglist)));
+      break;
+
+    case BUILT_IN_CABS:
+    case BUILT_IN_CABSF:
+    case BUILT_IN_CABSL:
+      return fold_builtin_cabs (arglist, type);
+
+    case BUILT_IN_SQRT:
+    case BUILT_IN_SQRTF:
+    case BUILT_IN_SQRTL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	{
+	  enum built_in_function fcode;
+	  tree arg = TREE_VALUE (arglist);
+
+	  /* Optimize sqrt of constant value.  */
+	  if (TREE_CODE (arg) == REAL_CST
+	      && ! TREE_CONSTANT_OVERFLOW (arg))
+	    {
+	      REAL_VALUE_TYPE r, x;
+
+	      x = TREE_REAL_CST (arg);
+	      if (real_sqrt (&r, TYPE_MODE (type), &x)
+		  || (!flag_trapping_math && !flag_errno_math))
+		return build_real (type, r);
+	    }
+
+	  /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
+	  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 (build (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)).  */
+	  if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
+	    {
+	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
+	      
+	      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 =
+		    BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
+		  
+		  /* Adjust for the outer root.  */
+		  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 sqrt(pow(x,y)) = pow(x,y*0.5).  */
+	  if (flag_unsafe_math_optimizations
+	      && (fcode == BUILT_IN_POW
+		  || 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 = fold (build (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);
+	    }
+	}
+      break;
+
+    case BUILT_IN_CBRT:
+    case BUILT_IN_CBRTF:
+    case BUILT_IN_CBRTL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	{
+	  tree arg = TREE_VALUE (arglist);
+	  const enum built_in_function fcode = builtin_mathfn_code (arg);
+
+	  /* Optimize cbrt of constant value.  */
+	  if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
+	    return arg;
+
+	  /* Optimize cbrt(expN(x)) -> expN(x/3).  */
+	  if (flag_unsafe_math_optimizations && 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 (build (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).  */
+	  /* We don't optimize cbrt(cbrt(x)) -> pow(x,1/9) because if
+             x is negative pow will error but cbrt won't.  */
+	  if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode))
+	    {
+	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
+
+	      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);
+		}
+	      
+	    }
+	}
+      break;
+
+    case BUILT_IN_SIN:
+    case BUILT_IN_SINF:
+    case BUILT_IN_SINL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	{
+	  tree arg = TREE_VALUE (arglist);
+
+	  /* Optimize sin(0.0) = 0.0.  */
+	  if (real_zerop (arg))
+	    return arg;
+	}
+      break;
+
+    case BUILT_IN_COS:
+    case BUILT_IN_COSF:
+    case BUILT_IN_COSL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	{
+	  tree arg = TREE_VALUE (arglist);
+
+	  /* Optimize cos(0.0) = 1.0.  */
+	  if (real_zerop (arg))
+	    return build_real (type, dconst1);
+
+	  /* Optimize cos(-x) into cos(x).  */
+	  if (TREE_CODE (arg) == NEGATE_EXPR)
+	    {
+	      tree arglist = build_tree_list (NULL_TREE,
+					      TREE_OPERAND (arg, 0));
+	      return build_function_call_expr (fndecl, arglist);
+	    }
+	}
+      break;
+
+    case BUILT_IN_EXP:
+    case BUILT_IN_EXPF:
+    case BUILT_IN_EXPL:
+      return fold_builtin_exponent (exp, &dconste);
+    case BUILT_IN_EXP2:
+    case BUILT_IN_EXP2F:
+    case BUILT_IN_EXP2L:
+      return fold_builtin_exponent (exp, &dconst2);
+    case BUILT_IN_EXP10:
+    case BUILT_IN_EXP10F:
+    case BUILT_IN_EXP10L:
+    case BUILT_IN_POW10:
+    case BUILT_IN_POW10F:
+    case BUILT_IN_POW10L:
+      return fold_builtin_exponent (exp, &dconst10);
+    case BUILT_IN_LOG:
+    case BUILT_IN_LOGF:
+    case BUILT_IN_LOGL:
+      return fold_builtin_logarithm (exp, &dconste);
+      break;
+    case BUILT_IN_LOG2:
+    case BUILT_IN_LOG2F:
+    case BUILT_IN_LOG2L:
+      return fold_builtin_logarithm (exp, &dconst2);
+      break;
+    case BUILT_IN_LOG10:
+    case BUILT_IN_LOG10F:
+    case BUILT_IN_LOG10L:
+      return fold_builtin_logarithm (exp, &dconst10);
+      break;
+
+    case BUILT_IN_TAN:
+    case BUILT_IN_TANF:
+    case BUILT_IN_TANL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	{
+	  enum built_in_function fcode;
+	  tree arg = TREE_VALUE (arglist);
+
+	  /* Optimize tan(0.0) = 0.0.  */
+	  if (real_zerop (arg))
+	    return arg;
+
+	  /* Optimize tan(atan(x)) = x.  */
+	  fcode = builtin_mathfn_code (arg);
+	  if (flag_unsafe_math_optimizations
+	      && (fcode == BUILT_IN_ATAN
+		  || fcode == BUILT_IN_ATANF
+		  || fcode == BUILT_IN_ATANL))
+	    return TREE_VALUE (TREE_OPERAND (arg, 1));
+	}
+      break;
+
+    case BUILT_IN_ATAN:
+    case BUILT_IN_ATANF:
+    case BUILT_IN_ATANL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+	{
+	  tree arg = TREE_VALUE (arglist);
+
+	  /* Optimize atan(0.0) = 0.0.  */
+	  if (real_zerop (arg))
+	    return arg;
+
+	  /* Optimize atan(1.0) = pi/4.  */
+	  if (real_onep (arg))
+	    {
+	      REAL_VALUE_TYPE cst;
+
+	      real_convert (&cst, TYPE_MODE (type), &dconstpi);
+	      SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
+	      return build_real (type, cst);
+	    }
+	}
+      break;
+
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+      if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+	{
+	  enum built_in_function fcode;
+	  tree arg0 = TREE_VALUE (arglist);
+	  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+	  /* Optimize pow(1.0,y) = 1.0.  */
+	  if (real_onep (arg0))
+	    return omit_one_operand (type, build_real (type, dconst1), arg1);
+
+	  if (TREE_CODE (arg1) == REAL_CST
+	      && ! TREE_CONSTANT_OVERFLOW (arg1))
+	    {
+	      REAL_VALUE_TYPE c;
+	      c = TREE_REAL_CST (arg1);
+
+	      /* Optimize pow(x,0.0) = 1.0.  */
+	      if (REAL_VALUES_EQUAL (c, dconst0))
+		return omit_one_operand (type, build_real (type, dconst1),
+					 arg0);
+
+	      /* Optimize pow(x,1.0) = x.  */
+	      if (REAL_VALUES_EQUAL (c, dconst1))
+		return arg0;
+
+	      /* Optimize pow(x,-1.0) = 1.0/x.  */
+	      if (REAL_VALUES_EQUAL (c, dconstm1))
+		return fold (build (RDIV_EXPR, type,
+				    build_real (type, dconst1),
+				    arg0));
+
+	      /* Optimize pow(x,0.5) = sqrt(x).  */
+	      if (flag_unsafe_math_optimizations
+		  && REAL_VALUES_EQUAL (c, dconsthalf))
+		{
+		  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);
+		    }
+		}
+
+	      /* Attempt to evaluate pow at compile-time.  */
+	      if (TREE_CODE (arg0) == REAL_CST
+		  && ! TREE_CONSTANT_OVERFLOW (arg0))
+		{
+		  REAL_VALUE_TYPE cint;
+		  HOST_WIDE_INT n;
+
+		  n = real_to_integer (&c);
+		  real_from_integer (&cint, VOIDmode, n,
+				     n < 0 ? -1 : 0, 0);
+		  if (real_identical (&c, &cint))
+		    {
+		      REAL_VALUE_TYPE x;
+		      bool inexact;
+
+		      x = TREE_REAL_CST (arg0);
+		      inexact = real_powi (&x, TYPE_MODE (type), &x, n);
+		      if (flag_unsafe_math_optimizations || !inexact)
+			return build_real (type, x);
+		    }
+		}
+	    }
+
+	  /* Optimize pow(expN(x),y) = expN(x*y).  */
+	  fcode = builtin_mathfn_code (arg0);
+	  if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
+	    {
+	      tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+	      tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
+	      arg = fold (build (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 (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode))
+	    {
+	      tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+	      tree narg1 = fold (build (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(pow(x,y),z) = pow(x,y*z).  */
+	  if (flag_unsafe_math_optimizations
+	      && (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 (build (MULT_EXPR, type, arg01, arg1));
+	      arglist = tree_cons (NULL_TREE, arg00,
+				   build_tree_list (NULL_TREE, narg1));
+	      return build_function_call_expr (fndecl, arglist);
+	    }
+	}
+      break;
+
+    case BUILT_IN_INF:
+    case BUILT_IN_INFF:
+    case BUILT_IN_INFL:
+      return fold_builtin_inf (type, true);
+
+    case BUILT_IN_HUGE_VAL:
+    case BUILT_IN_HUGE_VALF:
+    case BUILT_IN_HUGE_VALL:
+      return fold_builtin_inf (type, false);
+
+    case BUILT_IN_NAN:
+    case BUILT_IN_NANF:
+    case BUILT_IN_NANL:
+      return fold_builtin_nan (arglist, type, true);
+
+    case BUILT_IN_NANS:
+    case BUILT_IN_NANSF:
+    case BUILT_IN_NANSL:
+      return fold_builtin_nan (arglist, type, false);
+
+    case BUILT_IN_FLOOR:
+    case BUILT_IN_FLOORF:
+    case BUILT_IN_FLOORL:
+      return fold_builtin_floor (exp);
+
+    case BUILT_IN_CEIL:
+    case BUILT_IN_CEILF:
+    case BUILT_IN_CEILL:
+      return fold_builtin_ceil (exp);
+
+    case BUILT_IN_TRUNC:
+    case BUILT_IN_TRUNCF:
+    case BUILT_IN_TRUNCL:
+      return fold_builtin_trunc (exp);
+
+    case BUILT_IN_ROUND:
+    case BUILT_IN_ROUNDF:
+    case BUILT_IN_ROUNDL:
+      return fold_builtin_round (exp);
+
+    case BUILT_IN_NEARBYINT:
+    case BUILT_IN_NEARBYINTF:
+    case BUILT_IN_NEARBYINTL:
+    case BUILT_IN_RINT:
+    case BUILT_IN_RINTF:
+    case BUILT_IN_RINTL:
+      return fold_trunc_transparent_mathfn (exp);
+
+    case BUILT_IN_FFS:
+    case BUILT_IN_FFSL:
+    case BUILT_IN_FFSLL:
+    case BUILT_IN_CLZ:
+    case BUILT_IN_CLZL:
+    case BUILT_IN_CLZLL:
+    case BUILT_IN_CTZ:
+    case BUILT_IN_CTZL:
+    case BUILT_IN_CTZLL:
+    case BUILT_IN_POPCOUNT:
+    case BUILT_IN_POPCOUNTL:
+    case BUILT_IN_POPCOUNTLL:
+    case BUILT_IN_PARITY:
+    case BUILT_IN_PARITYL:
+    case BUILT_IN_PARITYLL:
+      return fold_builtin_bitop (exp);
+
+    case BUILT_IN_MEMCPY:
+      return fold_builtin_memcpy (exp);
+
+    case BUILT_IN_MEMPCPY:
+      return fold_builtin_mempcpy (exp);
+
+    case BUILT_IN_MEMMOVE:
+      return fold_builtin_memmove (exp);
+
+    case BUILT_IN_STRCPY:
+      return fold_builtin_strcpy (exp);
+
+    case BUILT_IN_STRNCPY:
+      return fold_builtin_strncpy (exp);
+
+    case BUILT_IN_MEMCMP:
+      return fold_builtin_memcmp (exp);
+
+    case BUILT_IN_STRCMP:
+      return fold_builtin_strcmp (exp);
+
+    case BUILT_IN_STRNCMP:
+      return fold_builtin_strncmp (exp);
+
+    case BUILT_IN_SIGNBIT:
+    case BUILT_IN_SIGNBITF:
+    case BUILT_IN_SIGNBITL:
+      return fold_builtin_signbit (exp);
+
+    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);
+
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+/* 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
+    {
+      code = va_arg (ap, enum tree_code);
+      switch (code)
+	{
+	case 0:
+	  /* This signifies an ellipses, any further arguments are all ok.  */
+	  res = 1;
+	  goto end;
+	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
+	      || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
+	    goto end;
+	  break;
+	}
+      arglist = TREE_CHAIN (arglist);
+    }
+  while (1);
+
+  /* We need gotos here since we can only have one VA_CLOSE in a
+     function.  */
+ end: ;
+  va_end (ap);
+
+  return res;
+}
+



More information about the Gcc-patches mailing list