OSDN Git Service

* regrename.c (copy_value): Fix comment.
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index e907752..c966c0e 100644 (file)
@@ -16,8 +16,8 @@ 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.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -111,15 +111,15 @@ static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
 static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
-static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode);
-static rtx expand_builtin_bcopy (tree, tree);
+static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
+static rtx expand_builtin_bcopy (tree);
 static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
 static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
 static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
-static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
+static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
 static rtx expand_builtin_bzero (tree);
 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
@@ -351,7 +351,7 @@ c_strlen (tree src, int only_value)
      runtime.  */
   if (offset < 0 || offset > max)
     {
-      warning ("offset outside bounds of constant string");
+      warning (0, "offset outside bounds of constant string");
       return 0;
     }
 
@@ -945,7 +945,7 @@ expand_builtin_prefetch (tree arglist)
   /* Argument 1 must be either zero or one.  */
   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
     {
-      warning ("invalid second argument to %<__builtin_prefetch%>;"
+      warning (0, "invalid second argument to %<__builtin_prefetch%>;"
               " using zero");
       op1 = const0_rtx;
     }
@@ -960,7 +960,7 @@ expand_builtin_prefetch (tree arglist)
   /* Argument 2 must be 0, 1, 2, or 3.  */
   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
     {
-      warning ("invalid third argument to %<__builtin_prefetch%>; using zero");
+      warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
       op2 = const0_rtx;
     }
 
@@ -2808,7 +2808,8 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
 
       /* Copy word part most expediently.  */
       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
-                                  BLOCK_OP_NORMAL);
+                                  CALL_EXPR_TAILCALL (exp)
+                                  ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
 
       if (dest_addr == 0)
        {
@@ -2915,7 +2916,7 @@ expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode m
 
 static rtx
 expand_builtin_memmove (tree arglist, tree type, rtx target,
-                       enum machine_mode mode)
+                       enum machine_mode mode, tree orig_exp)
 {
   if (!validate_arglist (arglist,
                         POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -2947,11 +2948,13 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
         normal memcpy.  */
       if (readonly_data_expr (src))
         {
-         tree const fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+         tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
          if (!fn)
            return 0;
-         return expand_expr (build_function_call_expr (fn, arglist),
-                             target, mode, EXPAND_NORMAL);
+         fn = build_function_call_expr (fn, arglist);
+         if (TREE_CODE (fn) == CALL_EXPR)
+           CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
+         return expand_expr (fn, target, mode, EXPAND_NORMAL);
        }
 
       /* If length is 1 and we can expand memcpy call inline,
@@ -2973,8 +2976,10 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
    if we failed the caller should emit a normal call.  */
 
 static rtx
-expand_builtin_bcopy (tree arglist, tree type)
+expand_builtin_bcopy (tree exp)
 {
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree type = TREE_TYPE (exp);
   tree src, dest, size, newarglist;
 
   if (!validate_arglist (arglist,
@@ -2994,7 +2999,7 @@ expand_builtin_bcopy (tree arglist, tree type)
   newarglist = tree_cons (NULL_TREE, src, newarglist);
   newarglist = tree_cons (NULL_TREE, dest, newarglist);
 
-  return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode);
+  return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
 }
 
 #ifndef HAVE_movstr
@@ -3288,7 +3293,8 @@ builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    convenient).  */
 
 static rtx
-expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
+                      tree orig_exp)
 {
   if (!validate_arglist (arglist,
                         POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -3336,7 +3342,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
                                    &c, dest_align))
            return 0;
 
-         val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
+         val = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val);
          val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
          val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
                               val_rtx);
@@ -3374,7 +3380,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
 
       dest_mem = get_memory_rtx (dest);
       set_mem_align (dest_mem, dest_align);
-      dest_addr = clear_storage (dest_mem, len_rtx);
+      dest_addr = clear_storage (dest_mem, len_rtx,
+                                CALL_EXPR_TAILCALL (orig_exp)
+                                ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
 
       if (dest_addr == 0)
        {
@@ -3390,8 +3398,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
    if we failed the caller should emit a normal call.  */
 
 static rtx
-expand_builtin_bzero (tree arglist)
+expand_builtin_bzero (tree exp)
 {
+  tree arglist = TREE_OPERAND (exp, 1);
   tree dest, size, newarglist;
 
   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -3409,7 +3418,7 @@ expand_builtin_bzero (tree arglist)
   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
   newarglist = tree_cons (NULL_TREE, dest, newarglist);
 
-  return expand_builtin_memset (newarglist, const0_rtx, VOIDmode);
+  return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
 }
 
 /* Expand expression EXP, which is a call to the memcmp built-in function.
@@ -3548,7 +3557,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
     tree len, len1, len2;
     rtx arg1_rtx, arg2_rtx, arg3_rtx;
     rtx result, insn;
-    tree fndecl;
+    tree fndecl, fn;
 
     int arg1_align
       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
@@ -3632,8 +3641,10 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
     arglist = build_tree_list (NULL_TREE, arg2);
     arglist = tree_cons (NULL_TREE, arg1, arglist);
     fndecl = get_callee_fndecl (exp);
-    exp = build_function_call_expr (fndecl, arglist);
-    return expand_call (exp, target, target == const0_rtx);
+    fn = build_function_call_expr (fndecl, arglist);
+    if (TREE_CODE (fn) == CALL_EXPR)
+      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+    return expand_call (fn, target, target == const0_rtx);
   }
 #endif
   return 0;
@@ -3670,7 +3681,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
     tree len, len1, len2;
     rtx arg1_rtx, arg2_rtx, arg3_rtx;
     rtx result, insn;
-    tree fndecl;
+    tree fndecl, fn;
 
     int arg1_align
       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
@@ -3716,8 +3727,8 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
       return 0;
 
     /* The actual new length parameter is MIN(len,arg3).  */
-    len = fold (build2 (MIN_EXPR, TREE_TYPE (len), len,
-                       fold_convert (TREE_TYPE (len), arg3)));
+    len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
+                      fold_convert (TREE_TYPE (len), arg3));
 
     /* If we don't have POINTER_TYPE, call the function.  */
     if (arg1_align == 0 || arg2_align == 0)
@@ -3760,8 +3771,10 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
     arglist = tree_cons (NULL_TREE, arg2, arglist);
     arglist = tree_cons (NULL_TREE, arg1, arglist);
     fndecl = get_callee_fndecl (exp);
-    exp = build_function_call_expr (fndecl, arglist);
-    return expand_call (exp, target, target == const0_rtx);
+    fn = build_function_call_expr (fndecl, arglist);
+    if (TREE_CODE (fn) == CALL_EXPR)
+      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+    return expand_call (fn, target, target == const0_rtx);
   }
 #endif
   return 0;
@@ -3812,7 +3825,7 @@ expand_builtin_strcat (tree arglist, tree type, rtx target, enum machine_mode mo
                                                                 dst)));
              /* Create (dst + (cast) strlen (dst)).  */
              newdst = fold_convert (TREE_TYPE (dst), newdst);
-             newdst = fold (build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
+             newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
 
              /* Prepend the new dst argument.  */
              arglist = tree_cons (NULL_TREE, newdst, arglist);
@@ -3996,7 +4009,7 @@ stabilize_va_list (tree valist, int needs_lvalue)
            return valist;
 
          pt = build_pointer_type (va_list_type_node);
-         valist = fold (build1 (ADDR_EXPR, pt, valist));
+         valist = fold_build1 (ADDR_EXPR, pt, valist);
          TREE_SIDE_EFFECTS (valist) = 1;
        }
 
@@ -4128,11 +4141,11 @@ std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
   if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
     {
       /* Small args are padded downward.  */
-      t = fold (build2 (GT_EXPR, sizetype, rounded_size, size_int (align)));
-      t = fold (build3 (COND_EXPR, sizetype, t, size_zero_node,
-                       size_binop (MINUS_EXPR, rounded_size, type_size)));
+      t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
+      t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+                      size_binop (MINUS_EXPR, rounded_size, type_size));
       t = fold_convert (TREE_TYPE (addr), t);
-      addr = fold (build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t));
+      addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
     }
 
   /* Compute new value for AP.  */
@@ -4220,12 +4233,12 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
       /* Unfortunately, this is merely undefined, rather than a constraint
         violation, so we cannot make this an error.  If this call is never
         executed, the program is still strictly conforming.  */
-      warning ("%qT is promoted to %qT when passed through %<...%>",
+      warning (0, "%qT is promoted to %qT when passed through %<...%>",
               type, promoted_type);
       if (! gave_help)
        {
          gave_help = true;
-         warning ("(so you should pass %qT not %qT to %<va_arg%>)",
+         warning (0, "(so you should pass %qT not %qT to %<va_arg%>)",
                   promoted_type, type);
        }
 
@@ -4262,7 +4275,8 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
        gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
 
       if (!targetm.gimplify_va_arg_expr)
-       /* Once most targets are converted this should abort.  */
+       /* FIXME:Once most targets are converted we should merely
+          assert this is non-null.  */
        return GS_ALL_DONE;
 
       *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
@@ -4364,9 +4378,9 @@ expand_builtin_frame_address (tree fndecl, tree arglist)
       if (tem == NULL)
        {
          if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
-           warning ("unsupported argument to %<__builtin_frame_address%>");
+           warning (0, "unsupported argument to %<__builtin_frame_address%>");
          else
-           warning ("unsupported argument to %<__builtin_return_address%>");
+           warning (0, "unsupported argument to %<__builtin_return_address%>");
          return const0_rtx;
        }
 
@@ -4692,15 +4706,16 @@ build_string_literal (int len, const char *str)
   return t;
 }
 
-/* Expand a call to printf or printf_unlocked with argument list ARGLIST.
+/* Expand EXP, a call to printf or printf_unlocked.
    Return 0 if a normal call should be emitted rather than transforming
    the function inline.  If convenient, the result should be placed in
    TARGET with mode MODE.  UNLOCKED indicates this is a printf_unlocked
    call.  */
 static rtx
-expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
+expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
                       bool unlocked)
 {
+  tree arglist = TREE_OPERAND (exp, 1);
   tree fn_putchar = unlocked
                    ? implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
                    : implicit_built_in_decls[BUILT_IN_PUTCHAR];
@@ -4791,19 +4806,22 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
 
   if (!fn)
     return 0;
-  return expand_expr (build_function_call_expr (fn, arglist),
-                     target, mode, EXPAND_NORMAL);
+  fn = build_function_call_expr (fn, arglist);
+  if (TREE_CODE (fn) == CALL_EXPR)
+    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+  return expand_expr (fn, target, mode, EXPAND_NORMAL);
 }
 
-/* Expand a call to fprintf or fprintf_unlocked with argument list ARGLIST.
+/* Expand EXP, a call to fprintf or fprintf_unlocked.
    Return 0 if a normal call should be emitted rather than transforming
    the function inline.  If convenient, the result should be placed in
    TARGET with mode MODE.  UNLOCKED indicates this is a fprintf_unlocked
    call.  */
 static rtx
-expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
+expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
                        bool unlocked)
 {
+  tree arglist = TREE_OPERAND (exp, 1);
   tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
                           : implicit_built_in_decls[BUILT_IN_FPUTC];
   tree fn_fputs = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
@@ -4885,8 +4903,10 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
 
   if (!fn)
     return 0;
-  return expand_expr (build_function_call_expr (fn, arglist),
-                     target, mode, EXPAND_NORMAL);
+  fn = build_function_call_expr (fn, arglist);
+  if (TREE_CODE (fn) == CALL_EXPR)
+    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+  return expand_expr (fn, target, mode, EXPAND_NORMAL);
 }
 
 /* Expand a call to sprintf with argument list ARGLIST.  Return 0 if
@@ -5109,8 +5129,8 @@ expand_builtin_signbit (tree exp, rtx target)
     if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
       return 0;
 
-    arg = fold (build2 (LT_EXPR, TREE_TYPE (exp), arg,
-                       build_real (TREE_TYPE (arg), dconst0)));
+    arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
+                      build_real (TREE_TYPE (arg), dconst0));
     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   }
 
@@ -5255,20 +5275,13 @@ expand_builtin_sync_operation (tree arglist, enum rtx_code code, bool after,
 {
   enum machine_mode mode;
   rtx addr, val, mem;
-  tree valt;
 
   /* Expand the operands.  */
   addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
   mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
 
   arglist = TREE_CHAIN (arglist);
-  valt = TREE_VALUE (arglist);
-  if (code == NOT && TREE_CONSTANT (valt))
-    {
-      valt = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (valt), valt);
-      code = AND;
-    }
-  val = expand_expr (valt, NULL, mode, EXPAND_NORMAL);
+  val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
 
   /* Note that we explicitly do not want any alias information for this
      memory, so that we kill all other live memories.  Otherwise we don't
@@ -5856,25 +5869,26 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       break;
 
     case BUILT_IN_MEMMOVE:
-      target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target, mode);
+      target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
+                                      mode, exp);
       if (target)
        return target;
       break;
 
     case BUILT_IN_BCOPY:
-      target = expand_builtin_bcopy (arglist, TREE_TYPE (exp));
+      target = expand_builtin_bcopy (exp);
       if (target)
        return target;
       break;
 
     case BUILT_IN_MEMSET:
-      target = expand_builtin_memset (arglist, target, mode);
+      target = expand_builtin_memset (arglist, target, mode, exp);
       if (target)
        return target;
       break;
 
     case BUILT_IN_BZERO:
-      target = expand_builtin_bzero (arglist);
+      target = expand_builtin_bzero (exp);
       if (target)
        return target;
       break;
@@ -5951,13 +5965,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       return const0_rtx;
 
     case BUILT_IN_PRINTF:
-      target = expand_builtin_printf (arglist, target, mode, false);
+      target = expand_builtin_printf (exp, target, mode, false);
       if (target)
        return target;
       break;
 
     case BUILT_IN_PRINTF_UNLOCKED:
-      target = expand_builtin_printf (arglist, target, mode, true);
+      target = expand_builtin_printf (exp, target, mode, true);
       if (target)
        return target;
       break;
@@ -5974,13 +5988,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       break;
 
     case BUILT_IN_FPRINTF:
-      target = expand_builtin_fprintf (arglist, target, mode, false);
+      target = expand_builtin_fprintf (exp, target, mode, false);
       if (target)
        return target;
       break;
 
     case BUILT_IN_FPRINTF_UNLOCKED:
-      target = expand_builtin_fprintf (arglist, target, mode, true);
+      target = expand_builtin_fprintf (exp, target, mode, true);
       if (target)
        return target;
       break;
@@ -6324,10 +6338,17 @@ fold_builtin_constant_p (tree arglist)
   /* If we know this is a constant, emit the constant of one.  */
   if (CONSTANT_CLASS_P (arglist)
       || (TREE_CODE (arglist) == CONSTRUCTOR
-         && TREE_CONSTANT (arglist))
-      || (TREE_CODE (arglist) == ADDR_EXPR
-         && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
+         && TREE_CONSTANT (arglist)))
     return integer_one_node;
+  if (TREE_CODE (arglist) == ADDR_EXPR)
+    {
+       tree op = TREE_OPERAND (arglist, 0);
+       if (TREE_CODE (op) == STRING_CST
+          || (TREE_CODE (op) == ARRAY_REF
+              && integer_zerop (TREE_OPERAND (op, 1))
+              && TREE_CODE (TREE_OPERAND (op, 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
@@ -6605,7 +6626,7 @@ fold_fixed_mathfn (tree fndecl, tree arglist)
   /* If argument is already integer valued, and we don't need to worry
      about setting errno, there's no need to perform rounding.  */
   if (! flag_errno_math && integer_valued_real_p (arg))
-    return fold (build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg));
+    return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
 
   if (optimize)
     {
@@ -6666,10 +6687,10 @@ fold_builtin_cabs (tree arglist, tree type)
   /* 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)));
+    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)));
+    return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
 
   /* Don't do this when optimizing for size.  */
   if (flag_unsafe_math_optimizations
@@ -6683,17 +6704,17 @@ fold_builtin_cabs (tree arglist, tree type)
 
          arg = builtin_save_expr (arg);
 
-         rpart = fold (build1 (REALPART_EXPR, type, arg));
-         ipart = fold (build1 (IMAGPART_EXPR, type, arg));
+         rpart = fold_build1 (REALPART_EXPR, type, arg);
+         ipart = fold_build1 (IMAGPART_EXPR, type, arg);
 
          rpart = builtin_save_expr (rpart);
          ipart = builtin_save_expr (ipart);
 
-         result = fold (build2 (PLUS_EXPR, type,
-                                fold (build2 (MULT_EXPR, type,
-                                              rpart, rpart)),
-                                fold (build2 (MULT_EXPR, type,
-                                              ipart, ipart))));
+         result = fold_build2 (PLUS_EXPR, type,
+                               fold_build2 (MULT_EXPR, type,
+                                            rpart, rpart),
+                               fold_build2 (MULT_EXPR, type,
+                                            ipart, ipart));
 
          arglist = build_tree_list (NULL_TREE, result);
          return build_function_call_expr (sqrtfn, arglist);
@@ -6733,9 +6754,9 @@ fold_builtin_sqrt (tree arglist, tree type)
   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
     {
       tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
-      arg = fold (build2 (MULT_EXPR, type,
-                         TREE_VALUE (TREE_OPERAND (arg, 1)),
-                         build_real (type, dconsthalf)));
+      arg = fold_build2 (MULT_EXPR, type,
+                        TREE_VALUE (TREE_OPERAND (arg, 1)),
+                        build_real (type, dconsthalf));
       arglist = build_tree_list (NULL_TREE, arg);
       return build_function_call_expr (expfn, arglist);
     }
@@ -6775,8 +6796,8 @@ fold_builtin_sqrt (tree arglist, tree type)
       tree narg1;
       if (!tree_expr_nonnegative_p (arg0))
        arg0 = build1 (ABS_EXPR, type, arg0);
-      narg1 = fold (build2 (MULT_EXPR, type, arg1,
-                           build_real (type, dconsthalf)));
+      narg1 = fold_build2 (MULT_EXPR, type, arg1,
+                          build_real (type, dconsthalf));
       arglist = tree_cons (NULL_TREE, arg0,
                           build_tree_list (NULL_TREE, narg1));
       return build_function_call_expr (powfn, arglist);
@@ -6808,9 +6829,9 @@ fold_builtin_cbrt (tree arglist, tree type)
          tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
          const REAL_VALUE_TYPE third_trunc =
            real_value_truncate (TYPE_MODE (type), dconstthird);
-         arg = fold (build2 (MULT_EXPR, type,
-                             TREE_VALUE (TREE_OPERAND (arg, 1)),
-                             build_real (type, third_trunc)));
+         arg = fold_build2 (MULT_EXPR, type,
+                            TREE_VALUE (TREE_OPERAND (arg, 1)),
+                            build_real (type, third_trunc));
          arglist = build_tree_list (NULL_TREE, arg);
          return build_function_call_expr (expfn, arglist);
        }
@@ -6869,8 +6890,8 @@ fold_builtin_cbrt (tree arglist, tree type)
              tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
              const REAL_VALUE_TYPE dconstroot
                = real_value_truncate (TYPE_MODE (type), dconstthird);
-             tree narg01 = fold (build2 (MULT_EXPR, type, arg01,
-                                         build_real (type, dconstroot)));
+             tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
+                                        build_real (type, dconstroot));
              arglist = tree_cons (NULL_TREE, arg00,
                                   build_tree_list (NULL_TREE, narg01));
              return build_function_call_expr (powfn, arglist);
@@ -7391,7 +7412,7 @@ fold_builtin_logarithm (tree fndecl, tree arglist,
              tree logfn;
              arglist = build_tree_list (NULL_TREE, x);
              logfn = build_function_call_expr (fndecl, arglist);
-             return fold (build2 (MULT_EXPR, type, exponent, logfn));
+             return fold_build2 (MULT_EXPR, type, exponent, logfn);
            }
        }
     }
@@ -7434,8 +7455,8 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
 
       /* Optimize pow(x,-1.0) = 1.0/x.  */
       if (REAL_VALUES_EQUAL (c, dconstm1))
-       return fold (build2 (RDIV_EXPR, type,
-                            build_real (type, dconst1), arg0));
+       return fold_build2 (RDIV_EXPR, type,
+                           build_real (type, dconst1), arg0);
 
       /* Optimize pow(x,0.5) = sqrt(x).  */
       if (flag_unsafe_math_optimizations
@@ -7491,7 +7512,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
         {
          tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
          tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
-         arg = fold (build2 (MULT_EXPR, type, arg, arg1));
+         arg = fold_build2 (MULT_EXPR, type, arg, arg1);
          arglist = build_tree_list (NULL_TREE, arg);
          return build_function_call_expr (expfn, arglist);
        }
@@ -7500,8 +7521,8 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
       if (BUILTIN_SQRT_P (fcode))
         {
          tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
-         tree narg1 = fold (build2 (MULT_EXPR, type, arg1,
-                                    build_real (type, dconsthalf)));
+         tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
+                                   build_real (type, dconsthalf));
 
          arglist = tree_cons (NULL_TREE, narg0,
                               build_tree_list (NULL_TREE, narg1));
@@ -7516,8 +7537,8 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
            {
              const REAL_VALUE_TYPE dconstroot
                = real_value_truncate (TYPE_MODE (type), dconstthird);
-             tree narg1 = fold (build2 (MULT_EXPR, type, arg1,
-                                        build_real (type, dconstroot)));
+             tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
+                                       build_real (type, dconstroot));
              arglist = tree_cons (NULL_TREE, arg,
                                   build_tree_list (NULL_TREE, narg1));
              return build_function_call_expr (fndecl, arglist);
@@ -7530,7 +7551,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
         {
          tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
          tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
-         tree narg1 = fold (build2 (MULT_EXPR, type, arg01, arg1));
+         tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
          arglist = tree_cons (NULL_TREE, arg00,
                               build_tree_list (NULL_TREE, narg1));
          return build_function_call_expr (fndecl, arglist);
@@ -7580,8 +7601,8 @@ fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
 
       /* Optimize pow(x,-1) = 1.0/x.  */
       if (c == -1)
-       return fold (build2 (RDIV_EXPR, type,
-                            build_real (type, dconst1), arg0));
+       return fold_build2 (RDIV_EXPR, type,
+                          build_real (type, dconst1), arg0);
     }
 
   return NULL_TREE;
@@ -7710,11 +7731,11 @@ fold_builtin_mempcpy (tree arglist, tree type, int endp)
            return omit_one_operand (type, dest, len);
 
          if (endp == 2)
-           len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len,
-                               ssize_int (1)));
+           len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
+                              ssize_int (1));
       
          len = fold_convert (TREE_TYPE (dest), len);
-         len = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len));
+         len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
          return fold_convert (type, len);
        }
     }
@@ -7898,7 +7919,7 @@ fold_builtin_memcmp (tree arglist)
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
                                                      arg2)));
-      return fold (build2 (MINUS_EXPR, integer_type_node, ind1, ind2));
+      return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
     }
 
   return 0;
@@ -7957,7 +7978,7 @@ fold_builtin_strcmp (tree arglist)
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
                                                      arg2)));
-      return fold (build1 (NEGATE_EXPR, integer_type_node, temp));
+      return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
     }
 
   return 0;
@@ -8029,7 +8050,7 @@ fold_builtin_strncmp (tree arglist)
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
                                                      arg2)));
-      return fold (build1 (NEGATE_EXPR, integer_type_node, temp));
+      return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
     }
 
   /* If len parameter is one, return an expression corresponding to
@@ -8046,7 +8067,7 @@ fold_builtin_strncmp (tree arglist)
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
                                                      arg2)));
-      return fold (build2 (MINUS_EXPR, integer_type_node, ind1, ind2));
+      return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
     }
 
   return 0;
@@ -8083,8 +8104,8 @@ fold_builtin_signbit (tree fndecl, tree arglist)
 
   /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
   if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
-    return fold (build2 (LT_EXPR, type, arg,
-                        build_real (TREE_TYPE (arg), dconst0)));
+    return fold_build2 (LT_EXPR, type, arg,
+                       build_real (TREE_TYPE (arg), dconst0));
 
   return NULL_TREE;
 }
@@ -8126,7 +8147,7 @@ fold_builtin_copysign (tree fndecl, tree arglist, tree type)
      Remember to evaluate Y for side-effects.  */
   if (tree_expr_nonnegative_p (arg2))
     return omit_one_operand (type,
-                            fold (build1 (ABS_EXPR, type, arg1)),
+                            fold_build1 (ABS_EXPR, type, arg1),
                             arg2);
 
   /* Strip sign changing operations for the first argument.  */
@@ -8155,8 +8176,8 @@ fold_builtin_isascii (tree arglist)
       arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
                    build_int_cst (NULL_TREE,
                                   ~ (unsigned HOST_WIDE_INT) 0x7f));
-      arg = fold (build2 (EQ_EXPR, integer_type_node,
-                         arg, integer_zero_node));
+      arg = fold_build2 (EQ_EXPR, integer_type_node,
+                        arg, integer_zero_node);
 
       if (in_gimple_form && !TREE_CONSTANT (arg))
         return NULL_TREE;
@@ -8177,8 +8198,8 @@ fold_builtin_toascii (tree arglist)
       /* Transform toascii(c) -> (c & 0x7f).  */
       tree arg = TREE_VALUE (arglist);
 
-      return fold (build2 (BIT_AND_EXPR, integer_type_node, arg,
-                          build_int_cst (NULL_TREE, 0x7f)));
+      return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
+                         build_int_cst (NULL_TREE, 0x7f));
     }
 }
 
@@ -8228,7 +8249,7 @@ fold_builtin_fabs (tree arglist, tree type)
   arg = fold_convert (type, arg);
   if (TREE_CODE (arg) == REAL_CST)
     return fold_abs_const (arg, type);
-  return fold (build1 (ABS_EXPR, type, arg));
+  return fold_build1 (ABS_EXPR, type, arg);
 }
 
 /* Fold a call to abs, labs, llabs or imaxabs.  */
@@ -8245,7 +8266,7 @@ fold_builtin_abs (tree arglist, tree type)
   arg = fold_convert (type, arg);
   if (TREE_CODE (arg) == INTEGER_CST)
     return fold_abs_const (arg, type);
-  return fold (build1 (ABS_EXPR, type, arg));
+  return fold_build1 (ABS_EXPR, type, arg);
 }
 
 /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
@@ -8325,7 +8346,7 @@ fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
        }
 
       arg = builtin_save_expr (arg);
-      return fold (build2 (UNORDERED_EXPR, type, arg, arg));
+      return fold_build2 (UNORDERED_EXPR, type, arg, arg);
 
     default:
       gcc_unreachable ();
@@ -8400,51 +8421,13 @@ fold_builtin_unordered_cmp (tree fndecl, tree arglist,
     {
       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
        return omit_two_operands (type, integer_zero_node, arg0, arg1);
-      return fold (build2 (UNORDERED_EXPR, type, arg0, arg1));
+      return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
     }
 
   code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
                                                      : ordered_code;
-  return fold (build1 (TRUTH_NOT_EXPR, type,
-                      fold (build2 (code, type, arg0, arg1))));
-}
-
-/* Fold a call to one of the external complex multiply libcalls.  */
-
-static tree
-fold_builtin_complex_mul (tree type, tree arglist)
-{
-  tree ar, ai, br, bi;
-
-  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, REAL_TYPE,
-                        REAL_TYPE, VOID_TYPE))
-    return NULL;
-
-  ar = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-  ai = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-  br = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-  bi = TREE_VALUE (arglist);
-
-  return fold_complex_mult_parts (type, ar, ai, br, bi);
-}
-
-/* Fold a call to one of the external complex division libcalls.  */
-
-static tree
-fold_builtin_complex_div (tree type, tree arglist)
-{
-  tree ar, ai, br, bi;
-
-  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, REAL_TYPE,
-                        REAL_TYPE, VOID_TYPE))
-    return NULL;
-
-  ar = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-  ai = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-  br = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
-  bi = TREE_VALUE (arglist);
-
-  return fold_complex_div_parts (type, ar, ai, br, bi, RDIV_EXPR);
+  return fold_build1 (TRUTH_NOT_EXPR, type,
+                     fold_build2 (code, type, arg0, arg1));
 }
 
 /* Used by constant folding to simplify calls to builtin functions.  EXP is
@@ -8553,23 +8536,23 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     case BUILT_IN_CONJF:
     case BUILT_IN_CONJL:
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
-       return fold (build1 (CONJ_EXPR, type, TREE_VALUE (arglist)));
+       return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
       break;
 
     case BUILT_IN_CREAL:
     case BUILT_IN_CREALF:
     case BUILT_IN_CREALL:
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
-        return non_lvalue (fold (build1 (REALPART_EXPR, type,
-                                        TREE_VALUE (arglist))));
+        return non_lvalue (fold_build1 (REALPART_EXPR, type,
+                                       TREE_VALUE (arglist)));
       break;
 
     case BUILT_IN_CIMAG:
     case BUILT_IN_CIMAGF:
     case BUILT_IN_CIMAGL:
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
-        return non_lvalue (fold (build1 (IMAGPART_EXPR, type,
-                                        TREE_VALUE (arglist))));
+        return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
+                                       TREE_VALUE (arglist)));
       break;
 
     case BUILT_IN_CABS:
@@ -8805,12 +8788,6 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
       break;
 
     default:
-      if (fcode >= BUILT_IN_COMPLEX_MUL_MIN
-         && fcode <= BUILT_IN_COMPLEX_MUL_MAX)
-       return fold_builtin_complex_mul (type, arglist);
-      if (fcode >= BUILT_IN_COMPLEX_DIV_MIN
-         && fcode <= BUILT_IN_COMPLEX_DIV_MAX)
-       return fold_builtin_complex_div (type, arglist);
       break;
     }
 
@@ -8984,8 +8961,8 @@ fold_builtin_strstr (tree arglist, tree type)
            return build_int_cst (TREE_TYPE (s1), 0);
 
          /* Return an offset into the constant string argument.  */
-         tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1),
-                             s1, build_int_cst (TREE_TYPE (s1), r - p1)));
+         tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+                            s1, build_int_cst (TREE_TYPE (s1), r - p1));
          return fold_convert (type, tem);
        }
 
@@ -9054,8 +9031,8 @@ fold_builtin_strchr (tree arglist, tree type)
            return build_int_cst (TREE_TYPE (s1), 0);
 
          /* Return an offset into the constant string argument.  */
-         tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1),
-                             s1, build_int_cst (TREE_TYPE (s1), r - p1)));
+         tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+                            s1, build_int_cst (TREE_TYPE (s1), r - p1));
          return fold_convert (type, tem);
        }
       return 0;
@@ -9109,8 +9086,8 @@ fold_builtin_strrchr (tree arglist, tree type)
            return build_int_cst (TREE_TYPE (s1), 0);
 
          /* Return an offset into the constant string argument.  */
-         tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1),
-                             s1, build_int_cst (TREE_TYPE (s1), r - p1)));
+         tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+                            s1, build_int_cst (TREE_TYPE (s1), r - p1));
          return fold_convert (type, tem);
        }
 
@@ -9168,8 +9145,8 @@ fold_builtin_strpbrk (tree arglist, tree type)
            return build_int_cst (TREE_TYPE (s1), 0);
 
          /* Return an offset into the constant string argument.  */
-         tem = fold (build2 (PLUS_EXPR, TREE_TYPE (s1),
-                             s1, build_int_cst (TREE_TYPE (s1), r - p1)));
+         tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+                            s1, build_int_cst (TREE_TYPE (s1), r - p1));
          return fold_convert (type, tem);
        }
 
@@ -9492,7 +9469,7 @@ fold_builtin_next_arg (tree arglist)
     {
       /* Evidently an out of date version of <stdarg.h>; can't validate
         va_start's second argument, but can still work as intended.  */
-      warning ("%<__builtin_next_arg%> called without an argument");
+      warning (0, "%<__builtin_next_arg%> called without an argument");
       return true;
     }
   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
@@ -9527,7 +9504,7 @@ fold_builtin_next_arg (tree arglist)
             argument.  We just warn and set the arg to be the last
             argument so that we will get wrong-code because of
             it.  */
-         warning ("second parameter of %<va_start%> not last named argument");
+         warning (0, "second parameter of %<va_start%> not last named argument");
        }
       /* We want to verify the second parameter just once before the tree
          optimizers are run and then avoid keeping it in the tree,