OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index 2e42f46..80f2fbb 100644 (file)
@@ -1,6 +1,6 @@
 /* Expand builtin functions.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 /* Expand builtin functions.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -76,7 +76,6 @@ static 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, tree);
 static rtx c_readstr (const char *, enum machine_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree, tree);
-static tree build_string_literal (int, const char *);
 static int apply_args_size (void);
 static int apply_result_size (void);
 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
 static int apply_args_size (void);
 static int apply_result_size (void);
 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
@@ -95,6 +94,7 @@ static void expand_errno_check (tree, rtx);
 static rtx expand_builtin_mathfn (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
+static rtx expand_builtin_sincos (tree);
 static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
 static rtx expand_builtin_args_info (tree);
 static rtx expand_builtin_next_arg (void);
 static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
 static rtx expand_builtin_args_info (tree);
 static rtx expand_builtin_next_arg (void);
@@ -146,7 +146,6 @@ static tree fold_trunc_transparent_mathfn (tree, tree);
 static bool readonly_data_expr (tree);
 static rtx expand_builtin_fabs (tree, rtx, rtx);
 static rtx expand_builtin_signbit (tree, rtx);
 static bool readonly_data_expr (tree);
 static rtx expand_builtin_fabs (tree, rtx, rtx);
 static rtx expand_builtin_signbit (tree, rtx);
-static tree fold_builtin_cabs (tree, tree);
 static tree fold_builtin_sqrt (tree, tree);
 static tree fold_builtin_cbrt (tree, tree);
 static tree fold_builtin_pow (tree, tree, tree);
 static tree fold_builtin_sqrt (tree, tree);
 static tree fold_builtin_cbrt (tree, tree);
 static tree fold_builtin_pow (tree, tree, tree);
@@ -275,14 +274,28 @@ get_pointer_alignment (tree exp, unsigned int max_align)
        case ADDR_EXPR:
          /* See what we are pointing at and look at its alignment.  */
          exp = TREE_OPERAND (exp, 0);
        case ADDR_EXPR:
          /* See what we are pointing at and look at its alignment.  */
          exp = TREE_OPERAND (exp, 0);
+         inner = max_align;
+         while (handled_component_p (exp))
+           {
+             /* Fields in a structure can be packed, honor DECL_ALIGN
+                of the FIELD_DECL.  For all other references the conservative
+                alignment is the element type alignment.  */
+             if (TREE_CODE (exp) == COMPONENT_REF)
+               inner = MIN (inner, DECL_ALIGN (TREE_OPERAND (exp, 1)));
+             else
+               inner = MIN (inner, TYPE_ALIGN (TREE_TYPE (exp)));
+             exp = TREE_OPERAND (exp, 0);
+           }
          if (TREE_CODE (exp) == FUNCTION_DECL)
            align = FUNCTION_BOUNDARY;
          else if (DECL_P (exp))
          if (TREE_CODE (exp) == FUNCTION_DECL)
            align = FUNCTION_BOUNDARY;
          else if (DECL_P (exp))
-           align = DECL_ALIGN (exp);
+           align = MIN (inner, DECL_ALIGN (exp));
 #ifdef CONSTANT_ALIGNMENT
          else if (CONSTANT_CLASS_P (exp))
 #ifdef CONSTANT_ALIGNMENT
          else if (CONSTANT_CLASS_P (exp))
-           align = CONSTANT_ALIGNMENT (exp, align);
+           align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
 #endif
 #endif
+         else
+           align = MIN (align, inner);
          return MIN (align, max_align);
 
        default:
          return MIN (align, max_align);
 
        default:
@@ -496,14 +509,18 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
 #else
   rtx tem;
 
 #else
   rtx tem;
 
-  /* For a zero count, we don't care what frame address we return, so frame
-     pointer elimination is OK, and using the soft frame pointer is OK.
-     For a non-zero count, we require a stable offset from the current frame
-     pointer to the previous one, so we must use the hard frame pointer, and
+  /* For a zero count with __builtin_return_address, we don't care what
+     frame address we return, because target-specific definitions will
+     override us.  Therefore frame pointer elimination is OK, and using
+     the soft frame pointer is OK.
+
+     For a non-zero count, or a zero count with __builtin_frame_address,
+     we require a stable offset from the current frame pointer to the
+     previous one, so we must use the hard frame pointer, and
      we must disable frame pointer elimination.  */
      we must disable frame pointer elimination.  */
-  if (count == 0)
+  if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     tem = frame_pointer_rtx;
     tem = frame_pointer_rtx;
-  else 
+  else
     {
       tem = hard_frame_pointer_rtx;
 
     {
       tem = hard_frame_pointer_rtx;
 
@@ -700,7 +717,7 @@ expand_builtin_setjmp (tree arglist, rtx target)
       || REGNO (target) < FIRST_PSEUDO_REGISTER)
     target = gen_reg_rtx (TYPE_MODE (integer_type_node));
 
       || REGNO (target) < FIRST_PSEUDO_REGISTER)
     target = gen_reg_rtx (TYPE_MODE (integer_type_node));
 
-  buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
+  buf_addr = expand_normal (TREE_VALUE (arglist));
 
   next_lab = gen_label_rtx ();
   cont_lab = gen_label_rtx ();
 
   next_lab = gen_label_rtx ();
   cont_lab = gen_label_rtx ();
@@ -779,7 +796,7 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
 
       /* Pick up FP, label, and SP from the block and jump.  This code is
         from expand_goto in stmt.c; see there for detailed comments.  */
 
       /* Pick up FP, label, and SP from the block and jump.  This code is
         from expand_goto in stmt.c; see there for detailed comments.  */
-#if HAVE_nonlocal_goto
+#ifdef HAVE_nonlocal_goto
       if (HAVE_nonlocal_goto)
        /* We have to pass a value to the nonlocal_goto pattern that will
           get copied into the static_chain pointer, but it does not matter
       if (HAVE_nonlocal_goto)
        /* We have to pass a value to the nonlocal_goto pattern that will
           get copied into the static_chain pointer, but it does not matter
@@ -842,9 +859,9 @@ expand_builtin_nonlocal_goto (tree arglist)
   arglist = TREE_CHAIN (arglist);
   t_save_area = TREE_VALUE (arglist);
 
   arglist = TREE_CHAIN (arglist);
   t_save_area = TREE_VALUE (arglist);
 
-  r_label = expand_expr (t_label, NULL_RTX, VOIDmode, 0);
+  r_label = expand_normal (t_label);
   r_label = convert_memory_address (Pmode, r_label);
   r_label = convert_memory_address (Pmode, r_label);
-  r_save_area = expand_expr (t_save_area, NULL_RTX, VOIDmode, 0);
+  r_save_area = expand_normal (t_save_area);
   r_save_area = convert_memory_address (Pmode, r_save_area);
   r_fp = gen_rtx_MEM (Pmode, r_save_area);
   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
   r_save_area = convert_memory_address (Pmode, r_save_area);
   r_fp = gen_rtx_MEM (Pmode, r_save_area);
   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
@@ -852,7 +869,7 @@ expand_builtin_nonlocal_goto (tree arglist)
 
   current_function_has_nonlocal_goto = 1;
 
 
   current_function_has_nonlocal_goto = 1;
 
-#if HAVE_nonlocal_goto
+#ifdef HAVE_nonlocal_goto
   /* ??? We no longer need to pass the static chain value, afaik.  */
   if (HAVE_nonlocal_goto)
     emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
   /* ??? We no longer need to pass the static chain value, afaik.  */
   if (HAVE_nonlocal_goto)
     emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
@@ -975,7 +992,7 @@ expand_builtin_prefetch (tree arglist)
       error ("second argument to %<__builtin_prefetch%> must be a constant");
       arg1 = integer_zero_node;
     }
       error ("second argument to %<__builtin_prefetch%> must be a constant");
       arg1 = integer_zero_node;
     }
-  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+  op1 = expand_normal (arg1);
   /* Argument 1 must be either zero or one.  */
   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
     {
   /* Argument 1 must be either zero or one.  */
   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
     {
@@ -990,7 +1007,7 @@ expand_builtin_prefetch (tree arglist)
       error ("third argument to %<__builtin_prefetch%> must be a constant");
       arg2 = integer_zero_node;
     }
       error ("third argument to %<__builtin_prefetch%> must be a constant");
       arg2 = integer_zero_node;
     }
-  op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+  op2 = expand_normal (arg2);
   /* Argument 2 must be 0, 1, 2, or 3.  */
   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
     {
   /* Argument 2 must be 0, 1, 2, or 3.  */
   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
     {
@@ -1585,7 +1602,6 @@ type_to_class (tree type)
     {
     case VOID_TYPE:       return void_type_class;
     case INTEGER_TYPE:    return integer_type_class;
     {
     case VOID_TYPE:       return void_type_class;
     case INTEGER_TYPE:    return integer_type_class;
-    case CHAR_TYPE:       return char_type_class;
     case ENUMERAL_TYPE:           return enumeral_type_class;
     case BOOLEAN_TYPE:    return boolean_type_class;
     case POINTER_TYPE:    return pointer_type_class;
     case ENUMERAL_TYPE:           return enumeral_type_class;
     case BOOLEAN_TYPE:    return boolean_type_class;
     case POINTER_TYPE:    return pointer_type_class;
@@ -2019,8 +2035,8 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
   if (! stable)
     exp = build_function_call_expr (fndecl, arglist);
 
   if (! stable)
     exp = build_function_call_expr (fndecl, arglist);
 
-  op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
-  op1 = expand_expr (arg1, 0, VOIDmode, 0);
+  op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
+  op1 = expand_normal (arg1);
 
   start_sequence ();
 
 
   start_sequence ();
 
@@ -2064,7 +2080,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   tree fndecl = get_callee_fndecl (exp);
   tree arglist = TREE_OPERAND (exp, 1);
   enum machine_mode mode;
   tree fndecl = get_callee_fndecl (exp);
   tree arglist = TREE_OPERAND (exp, 1);
   enum machine_mode mode;
-  bool errno_set = false;
   tree arg, narg;
 
   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
   tree arg, narg;
 
   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -2084,9 +2099,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   /* Make a suitable register to place result in.  */
   mode = TYPE_MODE (TREE_TYPE (exp));
 
   /* Make a suitable register to place result in.  */
   mode = TYPE_MODE (TREE_TYPE (exp));
 
-  if (! flag_errno_math || ! HONOR_NANS (mode))
-    errno_set = false;
-
   /* Check if sincos insn is available, otherwise fallback
      to sin or cos insn.  */
   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
   /* Check if sincos insn is available, otherwise fallback
      to sin or cos insn.  */
   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
@@ -2147,9 +2159,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
 
       if (target != 0)
        {
 
       if (target != 0)
        {
-         if (errno_set)
-           expand_errno_check (exp, target);
-
          /* Output the entire sequence.  */
          insns = get_insns ();
          end_sequence ();
          /* Output the entire sequence.  */
          insns = get_insns ();
          end_sequence ();
@@ -2168,6 +2177,55 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   return target;
 }
 
   return target;
 }
 
+/* Expand a call to the builtin sincos math function.
+   Return 0 if a normal call should be emitted rather than expanding the
+   function in-line.  EXP is the expression that is a call to the builtin
+   function.  */
+
+static rtx
+expand_builtin_sincos (tree exp)
+{
+  rtx op0, op1, op2, target1, target2;
+  tree arglist = TREE_OPERAND (exp, 1);
+  enum machine_mode mode;
+  tree arg, sinp, cosp;
+  int result;
+
+  if (!validate_arglist (arglist, REAL_TYPE,
+                        POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+    return 0;
+
+  arg = TREE_VALUE (arglist);
+  sinp = TREE_VALUE (TREE_CHAIN (arglist));
+  cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+  /* Make a suitable register to place result in.  */
+  mode = TYPE_MODE (TREE_TYPE (arg));
+
+  /* Check if sincos insn is available, otherwise emit the call.  */
+  if (sincos_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+    return NULL_RTX;
+
+  target1 = gen_reg_rtx (mode);
+  target2 = gen_reg_rtx (mode);
+
+  op0 = expand_normal (arg);
+  op1 = expand_normal (build_fold_indirect_ref (sinp));
+  op2 = expand_normal (build_fold_indirect_ref (cosp));
+
+  /* Compute into target1 and target2.
+     Set TARGET to wherever the result comes back.  */
+  result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
+  gcc_assert (result);
+
+  /* Move target1 and target2 to the memory locations indicated
+     by op1 and op2.  */
+  emit_move_insn (op1, target1);
+  emit_move_insn (op2, target2);
+
+  return const0_rtx;
+}
+
 /* Expand a call to one of the builtin rounding functions (lfloor).
    If expanding via optab fails, lower expression to (int)(floor(x)).
    EXP is the expression that is a call to the builtin function;
 /* Expand a call to one of the builtin rounding functions (lfloor).
    If expanding via optab fails, lower expression to (int)(floor(x)).
    EXP is the expression that is a call to the builtin function;
@@ -2257,7 +2315,7 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
   gcc_assert (fallback_fndecl != NULL_TREE);
   exp = build_function_call_expr (fallback_fndecl, arglist);
 
   gcc_assert (fallback_fndecl != NULL_TREE);
   exp = build_function_call_expr (fallback_fndecl, arglist);
 
-  tmp = expand_builtin_mathfn (exp, NULL_RTX, NULL_RTX);
+  tmp = expand_normal (exp);
 
   /* Truncate the result of floating point optab to integer
      via expand_fix ().  */
 
   /* Truncate the result of floating point optab to integer
      via expand_fix ().  */
@@ -2415,7 +2473,7 @@ expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
   if (n < POWI_TABLE_SIZE)
     {
       if (cache[n])
   if (n < POWI_TABLE_SIZE)
     {
       if (cache[n])
-        return cache[n];
+       return cache[n];
 
       target = gen_reg_rtx (mode);
       cache[n] = target;
 
       target = gen_reg_rtx (mode);
       cache[n] = target;
@@ -2809,13 +2867,13 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
        return 0;
 
       /* If either SRC is not a pointer type, don't do this
        return 0;
 
       /* If either SRC is not a pointer type, don't do this
-         operation in-line.  */
+        operation in-line.  */
       if (src_align == 0)
        return 0;
 
       dest_mem = get_memory_rtx (dest, len);
       set_mem_align (dest_mem, dest_align);
       if (src_align == 0)
        return 0;
 
       dest_mem = get_memory_rtx (dest, len);
       set_mem_align (dest_mem, dest_align);
-      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+      len_rtx = expand_normal (len);
       src_str = c_getstr (src);
 
       /* If SRC is a string constant and block move would be done
       src_str = c_getstr (src);
 
       /* If SRC is a string constant and block move would be done
@@ -2892,9 +2950,9 @@ expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode m
 
       if (result)
        return expand_expr (result, target, mode, EXPAND_NORMAL);
 
       if (result)
        return expand_expr (result, target, mode, EXPAND_NORMAL);
-      
+
       /* If either SRC or DEST is not a pointer type, don't do this
       /* If either SRC or DEST is not a pointer type, don't do this
-         operation in-line.  */
+        operation in-line.  */
       if (dest_align == 0 || src_align == 0)
        return 0;
 
       if (dest_align == 0 || src_align == 0)
        return 0;
 
@@ -2902,7 +2960,7 @@ expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode m
       if (! host_integerp (len, 1))
        return 0;
 
       if (! host_integerp (len, 1))
        return 0;
 
-      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+      len_rtx = expand_normal (len);
       src_str = c_getstr (src);
 
       /* If SRC is a string constant and block move would be done
       src_str = c_getstr (src);
 
       /* If SRC is a string constant and block move would be done
@@ -2972,14 +3030,14 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
        return 0;
 
       /* If either SRC is not a pointer type, don't do this
        return 0;
 
       /* If either SRC is not a pointer type, don't do this
-         operation in-line.  */
+        operation in-line.  */
       if (src_align == 0)
        return 0;
 
       /* If src is categorized for a readonly section we can use
         normal memcpy.  */
       if (readonly_data_expr (src))
       if (src_align == 0)
        return 0;
 
       /* If src is categorized for a readonly section we can use
         normal memcpy.  */
       if (readonly_data_expr (src))
-        {
+       {
          tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
          if (!fn)
            return 0;
          tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
          if (!fn)
            return 0;
@@ -2992,12 +3050,12 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
       /* If length is 1 and we can expand memcpy call inline,
         it is ok to use memcpy as well.  */
       if (integer_onep (len))
       /* If length is 1 and we can expand memcpy call inline,
         it is ok to use memcpy as well.  */
       if (integer_onep (len))
-        {
+       {
          rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
                                            /*endp=*/0);
          if (ret)
            return ret;
          rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
                                            /*endp=*/0);
          if (ret)
            return ret;
-        }
+       }
 
       /* Otherwise, call the normal function.  */
       return 0;
 
       /* Otherwise, call the normal function.  */
       return 0;
@@ -3151,9 +3209,9 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
       rtx ret;
 
       /* Ensure we get an actual string whose length can be evaluated at
       rtx ret;
 
       /* Ensure we get an actual string whose length can be evaluated at
-         compile-time, not an expression containing a string.  This is
-         because the latter will potentially produce pessimized code
-         when used to produce the return value.  */
+        compile-time, not an expression containing a string.  This is
+        because the latter will potentially produce pessimized code
+        when used to produce the return value.  */
       src = TREE_VALUE (TREE_CHAIN (arglist));
       if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
        return expand_movstr (TREE_VALUE (arglist),
       src = TREE_VALUE (TREE_CHAIN (arglist));
       if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
        return expand_movstr (TREE_VALUE (arglist),
@@ -3173,11 +3231,11 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
 
       if (TREE_CODE (len) == INTEGER_CST)
        {
 
       if (TREE_CODE (len) == INTEGER_CST)
        {
-         rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+         rtx len_rtx = expand_normal (len);
 
          if (GET_CODE (len_rtx) == CONST_INT)
            {
 
          if (GET_CODE (len_rtx) == CONST_INT)
            {
-             ret = expand_builtin_strcpy (get_callee_fndecl (exp), 
+             ret = expand_builtin_strcpy (get_callee_fndecl (exp),
                                           arglist, target, mode);
 
              if (ret)
                                           arglist, target, mode);
 
              if (ret)
@@ -3237,7 +3295,7 @@ expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
       tree result = fold_builtin_strncpy (fndecl, arglist, slen);
       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
       tree result = fold_builtin_strncpy (fndecl, arglist, slen);
-      
+
       if (result)
        return expand_expr (result, target, mode, EXPAND_NORMAL);
 
       if (result)
        return expand_expr (result, target, mode, EXPAND_NORMAL);
 
@@ -3248,7 +3306,7 @@ expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
       slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
 
       /* We're required to pad with trailing zeros if the requested
       slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
 
       /* We're required to pad with trailing zeros if the requested
-         len is greater than strlen(s2)+1.  In that case try to
+        len is greater than strlen(s2)+1.  In that case try to
         use store_by_pieces, if it fails, punt.  */
       if (tree_int_cst_lt (slen, len))
        {
         use store_by_pieces, if it fails, punt.  */
       if (tree_int_cst_lt (slen, len))
        {
@@ -3335,12 +3393,14 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
       tree dest = TREE_VALUE (arglist);
       tree val = TREE_VALUE (TREE_CHAIN (arglist));
       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
       tree dest = TREE_VALUE (arglist);
       tree val = TREE_VALUE (TREE_CHAIN (arglist));
       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+      tree fndecl, fn;
+      enum built_in_function fcode;
       char c;
       char c;
-
-      unsigned int dest_align
-       = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+      unsigned int dest_align;
       rtx dest_mem, dest_addr, len_rtx;
 
       rtx dest_mem, dest_addr, len_rtx;
 
+      dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+
       /* If DEST is not a pointer type, don't do this
         operation in-line.  */
       if (dest_align == 0)
       /* If DEST is not a pointer type, don't do this
         operation in-line.  */
       if (dest_align == 0)
@@ -3354,15 +3414,21 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
          return expand_expr (dest, target, mode, EXPAND_NORMAL);
        }
 
          return expand_expr (dest, target, mode, EXPAND_NORMAL);
        }
 
-      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+      /* Stabilize the arguments in case we fail.  */
+      dest = builtin_save_expr (dest);
+      val = builtin_save_expr (val);
+      len = builtin_save_expr (len);
+
+      len_rtx = expand_normal (len);
       dest_mem = get_memory_rtx (dest, len);
 
       if (TREE_CODE (val) != INTEGER_CST)
        {
          rtx val_rtx;
 
       dest_mem = get_memory_rtx (dest, len);
 
       if (TREE_CODE (val) != INTEGER_CST)
        {
          rtx val_rtx;
 
-         val = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val);
-         val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
+         val_rtx = expand_normal (val);
+         val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
+                                    val_rtx, 0);
 
          /* Assume that we can memset by pieces if we can store the
           * the coefficients by pieces (in the required modes).
 
          /* Assume that we can memset by pieces if we can store the
           * the coefficients by pieces (in the required modes).
@@ -3373,14 +3439,14 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
              && can_store_by_pieces (tree_low_cst (len, 1),
                                      builtin_memset_read_str, &c, dest_align))
            {
              && can_store_by_pieces (tree_low_cst (len, 1),
                                      builtin_memset_read_str, &c, dest_align))
            {
-             val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node), 
+             val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
                                   val_rtx);
              store_by_pieces (dest_mem, tree_low_cst (len, 1),
                               builtin_memset_gen_str, val_rtx, dest_align, 0);
            }
                                   val_rtx);
              store_by_pieces (dest_mem, tree_low_cst (len, 1),
                               builtin_memset_gen_str, val_rtx, dest_align, 0);
            }
-         else if (!set_storage_via_setmem(dest_mem, len_rtx, val_rtx, 
-                                          dest_align))
-           return 0;
+         else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
+                                           dest_align))
+           goto do_libcall;
 
          dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
          dest_mem = convert_memory_address (ptr_mode, dest_mem);
 
          dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
          dest_mem = convert_memory_address (ptr_mode, dest_mem);
@@ -3388,7 +3454,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
        }
 
       if (target_char_cast (val, &c))
        }
 
       if (target_char_cast (val, &c))
-       return 0;
+       goto do_libcall;
 
       if (c)
        {
 
       if (c)
        {
@@ -3400,7 +3466,7 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
                             builtin_memset_read_str, &c, dest_align, 0);
          else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
                                            dest_align))
                             builtin_memset_read_str, &c, dest_align, 0);
          else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
                                            dest_align))
-           return 0;
+           goto do_libcall;
 
          dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
          dest_mem = convert_memory_address (ptr_mode, dest_mem);
 
          dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
          dest_mem = convert_memory_address (ptr_mode, dest_mem);
@@ -3419,6 +3485,19 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
        }
 
       return dest_addr;
        }
 
       return dest_addr;
+
+    do_libcall:
+      fndecl = get_callee_fndecl (orig_exp);
+      fcode = DECL_FUNCTION_CODE (fndecl);
+      gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
+      arglist = build_tree_list (NULL_TREE, len);
+      if (fcode == BUILT_IN_MEMSET)
+       arglist = tree_cons (NULL_TREE, val, arglist);
+      arglist = tree_cons (NULL_TREE, dest, arglist);
+      fn = build_function_call_expr (fndecl, arglist);
+      if (TREE_CODE (fn) == CALL_EXPR)
+       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
+      return expand_call (fn, target, target == const0_rtx);
     }
 }
 
     }
 }
 
@@ -3508,7 +3587,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
 
     arg1_rtx = get_memory_rtx (arg1, len);
     arg2_rtx = get_memory_rtx (arg2, len);
 
     arg1_rtx = get_memory_rtx (arg1, len);
     arg2_rtx = get_memory_rtx (arg2, len);
-    arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+    arg3_rtx = expand_normal (len);
 
     /* Set MEM_SIZE as appropriate.  */
     if (GET_CODE (arg3_rtx) == CONST_INT)
 
     /* Set MEM_SIZE as appropriate.  */
     if (GET_CODE (arg3_rtx) == CONST_INT)
@@ -3584,7 +3663,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
       rtx arg1_rtx, arg2_rtx;
       rtx result, insn = NULL_RTX;
       tree fndecl, fn;
       rtx arg1_rtx, arg2_rtx;
       rtx result, insn = NULL_RTX;
       tree fndecl, fn;
-      
+
       tree arg1 = TREE_VALUE (arglist);
       tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
       int arg1_align
       tree arg1 = TREE_VALUE (arglist);
       tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
       int arg1_align
@@ -3607,7 +3686,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
       /* Try to call cmpstrsi.  */
       if (HAVE_cmpstrsi)
        {
       /* Try to call cmpstrsi.  */
       if (HAVE_cmpstrsi)
        {
-         enum machine_mode insn_mode 
+         enum machine_mode insn_mode
            = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
 
          /* Make a place to write the result of the instruction.  */
            = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
 
          /* Make a place to write the result of the instruction.  */
@@ -3621,14 +3700,14 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
                               GEN_INT (MIN (arg1_align, arg2_align)));
        }
 #endif
                               GEN_INT (MIN (arg1_align, arg2_align)));
        }
 #endif
-#if HAVE_cmpstrnsi 
+#ifdef HAVE_cmpstrnsi
       /* Try to determine at least one length and call cmpstrnsi.  */
       /* Try to determine at least one length and call cmpstrnsi.  */
-      if (!insn && HAVE_cmpstrnsi) 
+      if (!insn && HAVE_cmpstrnsi)
        {
          tree len;
          rtx arg3_rtx;
 
        {
          tree len;
          rtx arg3_rtx;
 
-         enum machine_mode insn_mode 
+         enum machine_mode insn_mode
            = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
          tree len1 = c_strlen (arg1, 1);
          tree len2 = c_strlen (arg2, 1);
            = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
          tree len1 = c_strlen (arg1, 1);
          tree len2 = c_strlen (arg2, 1);
@@ -3664,10 +3743,9 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
 
          /* If both arguments have side effects, we cannot optimize.  */
          if (!len || TREE_SIDE_EFFECTS (len))
 
          /* If both arguments have side effects, we cannot optimize.  */
          if (!len || TREE_SIDE_EFFECTS (len))
-           return 0;
+           goto do_libcall;
 
 
-         /* Stabilize the arguments in case gen_cmpstrnsi fails.  */
-         arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+         arg3_rtx = expand_normal (len);
 
          /* Make a place to write the result of the instruction.  */
          result = target;
 
          /* Make a place to write the result of the instruction.  */
          result = target;
@@ -3697,6 +3775,9 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
 
       /* Expand the library call ourselves using a stabilized argument
         list to avoid re-evaluating the function's arguments twice.  */
 
       /* Expand the library call ourselves using a stabilized argument
         list to avoid re-evaluating the function's arguments twice.  */
+#ifdef HAVE_cmpstrnsi
+    do_libcall:
+#endif
       arglist = build_tree_list (NULL_TREE, arg2);
       arglist = tree_cons (NULL_TREE, arg1, arglist);
       fndecl = get_callee_fndecl (exp);
       arglist = build_tree_list (NULL_TREE, arg2);
       arglist = tree_cons (NULL_TREE, arg1, arglist);
       fndecl = get_callee_fndecl (exp);
@@ -3807,7 +3888,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
 
     arg1_rtx = get_memory_rtx (arg1, len);
     arg2_rtx = get_memory_rtx (arg2, len);
 
     arg1_rtx = get_memory_rtx (arg1, len);
     arg2_rtx = get_memory_rtx (arg2, len);
-    arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+    arg3_rtx = expand_normal (len);
     insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
                          GEN_INT (MIN (arg1_align, arg2_align)));
     if (insn)
     insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
                          GEN_INT (MIN (arg1_align, arg2_align)));
     if (insn)
@@ -3855,9 +3936,9 @@ expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode
       const char *p = c_getstr (src);
 
       /* If the string length is zero, return the dst parameter.  */
       const char *p = c_getstr (src);
 
       /* If the string length is zero, return the dst parameter.  */
-      if (p && *p == '\0')       
+      if (p && *p == '\0')
        return expand_expr (dst, target, mode, EXPAND_NORMAL);
        return expand_expr (dst, target, mode, EXPAND_NORMAL);
-      
+
       if (!optimize_size)
        {
          /* See if we can store by pieces into (dst + strlen(dst)).  */
       if (!optimize_size)
        {
          /* See if we can store by pieces into (dst + strlen(dst)).  */
@@ -3869,7 +3950,7 @@ expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode
          newsrc = builtin_save_expr (src);
          if (newsrc != src)
            arglist = build_tree_list (NULL_TREE, newsrc);
          newsrc = builtin_save_expr (src);
          if (newsrc != src)
            arglist = build_tree_list (NULL_TREE, newsrc);
-         else 
+         else
            arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe.  */
 
          dst = builtin_save_expr (dst);
            arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe.  */
 
          dst = builtin_save_expr (dst);
@@ -3892,12 +3973,12 @@ expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode
              end_sequence (); /* Stop sequence.  */
              return 0;
            }
              end_sequence (); /* Stop sequence.  */
              return 0;
            }
-         
+
          /* Output the entire sequence.  */
          insns = get_insns ();
          end_sequence ();
          emit_insn (insns);
          /* Output the entire sequence.  */
          insns = get_insns ();
          end_sequence ();
          emit_insn (insns);
-         
+
          return expand_expr (dst, target, mode, EXPAND_NORMAL);
        }
 
          return expand_expr (dst, target, mode, EXPAND_NORMAL);
        }
 
@@ -4162,7 +4243,8 @@ std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
 
   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
      requires greater alignment, we must perform dynamic alignment.  */
 
   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
      requires greater alignment, we must perform dynamic alignment.  */
-  if (boundary > align)
+  if (boundary > align
+      && !integer_zerop (TYPE_SIZE (type)))
     {
       t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
     {
       t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
@@ -4239,7 +4321,7 @@ build_va_arg_indirect_ref (tree addr)
 static tree
 dummy_object (tree type)
 {
 static tree
 dummy_object (tree type)
 {
-  tree t = convert (build_pointer_type (type), null_pointer_node);
+  tree t = build_int_cst (build_pointer_type (type), 0);
   return build1 (INDIRECT_REF, type, t);
 }
 
   return build1 (INDIRECT_REF, type, t);
 }
 
@@ -4265,7 +4347,7 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
     {
       /* If va_list is an array type, the argument may have decayed
         to a pointer type, e.g. by being passed to another function.
     {
       /* If va_list is an array type, the argument may have decayed
         to a pointer type, e.g. by being passed to another function.
-         In that case, unwrap both types so that we can compare the
+        In that case, unwrap both types so that we can compare the
         underlying records.  */
       if (TREE_CODE (have_va_type) == ARRAY_TYPE
          || POINTER_TYPE_P (have_va_type))
         underlying records.  */
       if (TREE_CODE (have_va_type) == ARRAY_TYPE
          || POINTER_TYPE_P (have_va_type))
@@ -4315,7 +4397,7 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
   else
     {
       /* Make it easier for the backends by protecting the valist argument
   else
     {
       /* Make it easier for the backends by protecting the valist argument
-         from multiple evaluations.  */
+        from multiple evaluations.  */
       if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
        {
          /* For this case, the backends will be expecting a pointer to
       if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
        {
          /* For this case, the backends will be expecting a pointer to
@@ -4473,7 +4555,7 @@ expand_builtin_alloca (tree arglist, rtx target)
     return 0;
 
   /* Compute the argument.  */
     return 0;
 
   /* Compute the argument.  */
-  op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
+  op0 = expand_normal (TREE_VALUE (arglist));
 
   /* Allocate the desired space.  */
   result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
 
   /* Allocate the desired space.  */
   result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
@@ -4671,7 +4753,7 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
                     probabilities.  */
                  if (integer_zerop (arg1))
                    taken = 1 - taken;
                     probabilities.  */
                  if (integer_zerop (arg1))
                    taken = 1 - taken;
-                 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
+                 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
                }
            }
 
                }
            }
 
@@ -4731,17 +4813,17 @@ expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
     return 0;
 
   arg = TREE_VALUE (arglist);
     return 0;
 
   arg = TREE_VALUE (arglist);
-  op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+  op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
 
   arg = TREE_VALUE (TREE_CHAIN (arglist));
 
   arg = TREE_VALUE (TREE_CHAIN (arglist));
-  op1 = expand_expr (arg, NULL, VOIDmode, 0);
+  op1 = expand_normal (arg);
 
   return expand_copysign (op0, op1, target);
 }
 
 /* Create a new constant string literal and return a char* pointer to it.
    The STRING_CST value is the LEN characters at STR.  */
 
   return expand_copysign (op0, op1, target);
 }
 
 /* Create a new constant string literal and return a char* pointer to it.
    The STRING_CST value is the LEN characters at STR.  */
-static tree
+tree
 build_string_literal (int len, const char *str)
 {
   tree t, elem, index, type;
 build_string_literal (int len, const char *str)
 {
   tree t, elem, index, type;
@@ -4802,12 +4884,12 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
 
   if (!init_target_chars())
     return 0;
 
   if (!init_target_chars())
     return 0;
-  
+
   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
   if (strcmp (fmt_str, target_percent_s_newline) == 0)
     {
       if (! arglist
   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
   if (strcmp (fmt_str, target_percent_s_newline) == 0)
     {
       if (! arglist
-          || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
+         || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
          || TREE_CHAIN (arglist))
        return 0;
       fn = fn_puts;
          || TREE_CHAIN (arglist))
        return 0;
       fn = fn_puts;
@@ -4825,7 +4907,7 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
     {
       /* We can't handle anything else with % args or %% ... yet.  */
       if (strchr (fmt_str, target_percent))
     {
       /* We can't handle anything else with % args or %% ... yet.  */
       if (strchr (fmt_str, target_percent))
-        return 0;
+       return 0;
 
       if (arglist)
        return 0;
 
       if (arglist)
        return 0;
@@ -4881,7 +4963,7 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
    call.  */
 static rtx
 expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
    call.  */
 static rtx
 expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
-                       bool unlocked)
+                       bool unlocked)
 {
   tree arglist = TREE_OPERAND (exp, 1);
   /* If we're using an unlocked function, assume the other unlocked
 {
   tree arglist = TREE_OPERAND (exp, 1);
   /* If we're using an unlocked function, assume the other unlocked
@@ -4918,12 +5000,12 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
 
   if (!init_target_chars())
     return 0;
 
   if (!init_target_chars())
     return 0;
-  
+
   /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
   if (strcmp (fmt_str, target_percent_s) == 0)
     {
       if (! arglist
   /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
   if (strcmp (fmt_str, target_percent_s) == 0)
     {
       if (! arglist
-          || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
+         || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
          || TREE_CHAIN (arglist))
        return 0;
       arg = TREE_VALUE (arglist);
          || TREE_CHAIN (arglist))
        return 0;
       arg = TREE_VALUE (arglist);
@@ -4947,7 +5029,7 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
     {
       /* We can't handle anything else with % args or %% ... yet.  */
       if (strchr (fmt_str, target_percent))
     {
       /* We can't handle anything else with % args or %% ... yet.  */
       if (strchr (fmt_str, target_percent))
-        return 0;
+       return 0;
 
       if (arglist)
        return 0;
 
       if (arglist)
        return 0;
@@ -5131,9 +5213,9 @@ expand_builtin_init_trampoline (tree arglist)
   arglist = TREE_CHAIN (arglist);
   t_chain = TREE_VALUE (arglist);
 
   arglist = TREE_CHAIN (arglist);
   t_chain = TREE_VALUE (arglist);
 
-  r_tramp = expand_expr (t_tramp, NULL_RTX, VOIDmode, 0);
-  r_func = expand_expr (t_func, NULL_RTX, VOIDmode, 0);
-  r_chain = expand_expr (t_chain, NULL_RTX, VOIDmode, 0);
+  r_tramp = expand_normal (t_tramp);
+  r_func = expand_normal (t_func);
+  r_chain = expand_normal (t_chain);
 
   /* Generate insns to initialize the trampoline.  */
   r_tramp = round_trampoline_addr (r_tramp);
 
   /* Generate insns to initialize the trampoline.  */
   r_tramp = round_trampoline_addr (r_tramp);
@@ -5157,7 +5239,7 @@ expand_builtin_adjust_trampoline (tree arglist)
   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
     return NULL_RTX;
 
   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
     return NULL_RTX;
 
-  tramp = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
+  tramp = expand_normal (TREE_VALUE (arglist));
   tramp = round_trampoline_addr (tramp);
 #ifdef TRAMPOLINE_ADJUST_ADDRESS
   TRAMPOLINE_ADJUST_ADDRESS (tramp);
   tramp = round_trampoline_addr (tramp);
 #ifdef TRAMPOLINE_ADJUST_ADDRESS
   TRAMPOLINE_ADJUST_ADDRESS (tramp);
@@ -5204,7 +5286,7 @@ expand_builtin_signbit (tree exp, rtx target)
     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   }
 
     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
   }
 
-  temp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+  temp = expand_normal (arg);
   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
     {
       imode = int_mode_for_mode (fmode);
   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
     {
       imode = int_mode_for_mode (fmode);
@@ -5217,9 +5299,9 @@ expand_builtin_signbit (tree exp, rtx target)
       imode = word_mode;
       /* Handle targets with different FP word orders.  */
       if (FLOAT_WORDS_BIG_ENDIAN)
       imode = word_mode;
       /* Handle targets with different FP word orders.  */
       if (FLOAT_WORDS_BIG_ENDIAN)
-        word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
+       word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
       else
       else
-        word = bitpos / BITS_PER_WORD;
+       word = bitpos / BITS_PER_WORD;
       temp = operand_subword_force (temp, word, fmode);
       bitpos = bitpos % BITS_PER_WORD;
     }
       temp = operand_subword_force (temp, word, fmode);
       bitpos = bitpos % BITS_PER_WORD;
     }
@@ -5255,7 +5337,7 @@ expand_builtin_signbit (tree exp, rtx target)
   else
     {
       /* Perform a logical right shift to place the signbit in the least
   else
     {
       /* Perform a logical right shift to place the signbit in the least
-         significant bit, then truncate the result to the desired mode
+        significant bit, then truncate the result to the desired mode
         and mask just this bit.  */
       temp = expand_shift (RSHIFT_EXPR, imode, temp,
                           build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
         and mask just this bit.  */
       temp = expand_shift (RSHIFT_EXPR, imode, temp,
                           build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
@@ -5325,6 +5407,8 @@ expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
   TREE_PUBLIC (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   TREE_NOTHROW (decl) = 1;
   TREE_PUBLIC (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   TREE_NOTHROW (decl) = 1;
+  DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+  DECL_VISIBILITY_SPECIFIED (decl) = 1;
   call = build_function_call_expr (decl, arglist);
 
   return expand_call (call, target, ignore);
   call = build_function_call_expr (decl, arglist);
 
   return expand_call (call, target, ignore);
@@ -5347,8 +5431,30 @@ get_builtin_sync_mode (int fcode_diff)
   return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
 }
 
   return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
 }
 
+/* Expand the memory expression LOC and return the appropriate memory operand
+   for the builtin_sync operations.  */
+
+static rtx
+get_builtin_sync_mem (tree loc, enum machine_mode mode)
+{
+  rtx addr, mem;
+
+  addr = expand_expr (loc, NULL, Pmode, EXPAND_SUM);
+
+  /* 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
+     satisfy the full barrier semantics of the intrinsic.  */
+  mem = validize_mem (gen_rtx_MEM (mode, addr));
+
+  set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
+  set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+  MEM_VOLATILE_P (mem) = 1;
+
+  return mem;
+}
+
 /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
 /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
-   ARGLIST is the operands list to the function.  CODE is the rtx code 
+   ARGLIST is the operands list to the function.  CODE is the rtx code
    that corresponds to the arithmetic or logical operation from the name;
    an exception here is that NOT actually means NAND.  TARGET is an optional
    place for us to store the results; AFTER is true if this is the
    that corresponds to the arithmetic or logical operation from the name;
    an exception here is that NOT actually means NAND.  TARGET is an optional
    place for us to store the results; AFTER is true if this is the
@@ -5360,20 +5466,14 @@ expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
                               enum rtx_code code, bool after,
                               rtx target, bool ignore)
 {
                               enum rtx_code code, bool after,
                               rtx target, bool ignore)
 {
-  rtx addr, val, mem;
+  rtx val, mem;
 
   /* Expand the operands.  */
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   arglist = TREE_CHAIN (arglist);
   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
 
 
   arglist = TREE_CHAIN (arglist);
   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
-     satisfy the full barrier semantics of the intrinsic.  */
-  mem = validize_mem (gen_rtx_MEM (mode, addr));
-  MEM_VOLATILE_P (mem) = 1;
-
   if (ignore)
     return expand_sync_operation (mem, val, code);
   else
   if (ignore)
     return expand_sync_operation (mem, val, code);
   else
@@ -5389,10 +5489,10 @@ static rtx
 expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
                                 bool is_bool, rtx target)
 {
 expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
                                 bool is_bool, rtx target)
 {
-  rtx addr, old_val, new_val, mem;
+  rtx old_val, new_val, mem;
 
   /* Expand the operands.  */
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   arglist = TREE_CHAIN (arglist);
   old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
 
   arglist = TREE_CHAIN (arglist);
   old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
@@ -5400,12 +5500,6 @@ expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
   arglist = TREE_CHAIN (arglist);
   new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
 
   arglist = TREE_CHAIN (arglist);
   new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
 
-  /* 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
-     satisfy the full barrier semantics of the intrinsic.  */
-  mem = validize_mem (gen_rtx_MEM (mode, addr));
-  MEM_VOLATILE_P (mem) = 1;
-
   if (is_bool)
     return expand_bool_compare_and_swap (mem, old_val, new_val, target);
   else
   if (is_bool)
     return expand_bool_compare_and_swap (mem, old_val, new_val, target);
   else
@@ -5422,20 +5516,14 @@ static rtx
 expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
                                  rtx target)
 {
 expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
                                  rtx target)
 {
-  rtx addr, val, mem;
+  rtx val, mem;
 
   /* Expand the operands.  */
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_NORMAL);
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   arglist = TREE_CHAIN (arglist);
   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
 
 
   arglist = TREE_CHAIN (arglist);
   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
-     satisfy the barrier semantics of the intrinsic.  */
-  mem = validize_mem (gen_rtx_MEM (mode, addr));
-  MEM_VOLATILE_P (mem) = 1;
-
   return expand_sync_lock_test_and_set (mem, val, target);
 }
 
   return expand_sync_lock_test_and_set (mem, val, target);
 }
 
@@ -5469,17 +5557,11 @@ static void
 expand_builtin_lock_release (enum machine_mode mode, tree arglist)
 {
   enum insn_code icode;
 expand_builtin_lock_release (enum machine_mode mode, tree arglist)
 {
   enum insn_code icode;
-  rtx addr, mem, insn;
+  rtx mem, insn;
   rtx val = const0_rtx;
 
   /* Expand the operands.  */
   rtx val = const0_rtx;
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, 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
-     satisfy the barrier semantics of the intrinsic.  */
-  mem = validize_mem (gen_rtx_MEM (mode, addr));
-  MEM_VOLATILE_P (mem) = 1;
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   /* If there is an explicit operation in the md file, use it.  */
   icode = sync_lock_release[mode];
 
   /* If there is an explicit operation in the md file, use it.  */
   icode = sync_lock_release[mode];
@@ -5563,7 +5645,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     CASE_FLT_FN (BUILT_IN_FABS):
       target = expand_builtin_fabs (arglist, target, subtarget);
       if (target)
     CASE_FLT_FN (BUILT_IN_FABS):
       target = expand_builtin_fabs (arglist, target, subtarget);
       if (target)
-        return target;
+       return target;
       break;
 
     CASE_FLT_FN (BUILT_IN_COPYSIGN):
       break;
 
     CASE_FLT_FN (BUILT_IN_COPYSIGN):
@@ -5651,6 +5733,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
        return target;
       break;
 
+    CASE_FLT_FN (BUILT_IN_SINCOS):
+      if (! flag_unsafe_math_optimizations)
+       break;
+      target = expand_builtin_sincos (exp);
+      if (target)
+       return target;
+      break;
+
     case BUILT_IN_APPLY_ARGS:
       return expand_builtin_apply_args ();
 
     case BUILT_IN_APPLY_ARGS:
       return expand_builtin_apply_args ();
 
@@ -5677,7 +5767,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
          rtx ops[3];
 
          for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
          rtx ops[3];
 
          for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
-           ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
+           ops[i] = expand_normal (TREE_VALUE (t));
 
          return expand_builtin_apply (ops[0], ops[1], ops[2]);
        }
 
          return expand_builtin_apply (ops[0], ops[1], ops[2]);
        }
@@ -5687,8 +5777,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
         memory returned by __builtin_apply.  */
     case BUILT_IN_RETURN:
       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
         memory returned by __builtin_apply.  */
     case BUILT_IN_RETURN:
       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
-       expand_builtin_return (expand_expr (TREE_VALUE (arglist),
-                                           NULL_RTX, VOIDmode, 0));
+       expand_builtin_return (expand_normal (TREE_VALUE (arglist)));
       return const0_rtx;
 
     case BUILT_IN_SAVEREGS:
       return const0_rtx;
 
     case BUILT_IN_SAVEREGS:
@@ -5700,7 +5789,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       /* Return the address of the first anonymous stack arg.  */
     case BUILT_IN_NEXT_ARG:
       if (fold_builtin_next_arg (arglist))
       /* Return the address of the first anonymous stack arg.  */
     case BUILT_IN_NEXT_ARG:
       if (fold_builtin_next_arg (arglist))
-        return const0_rtx;
+       return const0_rtx;
       return expand_builtin_next_arg ();
 
     case BUILT_IN_CLASSIFY_TYPE:
       return expand_builtin_next_arg ();
 
     case BUILT_IN_CLASSIFY_TYPE:
@@ -5921,9 +6010,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       else
        {
          rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
       else
        {
          rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
-                                     VOIDmode, 0);
-         rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
-                                  NULL_RTX, VOIDmode, 0);
+                                     VOIDmode, EXPAND_NORMAL);
+         rtx value = expand_normal (TREE_VALUE (TREE_CHAIN (arglist)));
 
          if (value != const1_rtx)
            {
 
          if (value != const1_rtx)
            {
@@ -5947,7 +6035,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
        {
          rtx buf_addr
       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
        {
          rtx buf_addr
-           = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
+           = expand_normal (TREE_VALUE (arglist));
 
          expand_builtin_update_setjmp_buf (buf_addr);
          return const0_rtx;
 
          expand_builtin_update_setjmp_buf (buf_addr);
          return const0_rtx;
@@ -6072,6 +6160,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_FETCH_AND_ADD_2:
     case BUILT_IN_FETCH_AND_ADD_4:
     case BUILT_IN_FETCH_AND_ADD_8:
     case BUILT_IN_FETCH_AND_ADD_2:
     case BUILT_IN_FETCH_AND_ADD_4:
     case BUILT_IN_FETCH_AND_ADD_8:
+    case BUILT_IN_FETCH_AND_ADD_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
       target = expand_builtin_sync_operation (mode, arglist, PLUS,
                                              false, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
       target = expand_builtin_sync_operation (mode, arglist, PLUS,
                                              false, target, ignore);
@@ -6083,6 +6172,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_FETCH_AND_SUB_2:
     case BUILT_IN_FETCH_AND_SUB_4:
     case BUILT_IN_FETCH_AND_SUB_8:
     case BUILT_IN_FETCH_AND_SUB_2:
     case BUILT_IN_FETCH_AND_SUB_4:
     case BUILT_IN_FETCH_AND_SUB_8:
+    case BUILT_IN_FETCH_AND_SUB_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
       target = expand_builtin_sync_operation (mode, arglist, MINUS,
                                              false, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
       target = expand_builtin_sync_operation (mode, arglist, MINUS,
                                              false, target, ignore);
@@ -6094,6 +6184,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_FETCH_AND_OR_2:
     case BUILT_IN_FETCH_AND_OR_4:
     case BUILT_IN_FETCH_AND_OR_8:
     case BUILT_IN_FETCH_AND_OR_2:
     case BUILT_IN_FETCH_AND_OR_4:
     case BUILT_IN_FETCH_AND_OR_8:
+    case BUILT_IN_FETCH_AND_OR_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
       target = expand_builtin_sync_operation (mode, arglist, IOR,
                                              false, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
       target = expand_builtin_sync_operation (mode, arglist, IOR,
                                              false, target, ignore);
@@ -6105,6 +6196,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_FETCH_AND_AND_2:
     case BUILT_IN_FETCH_AND_AND_4:
     case BUILT_IN_FETCH_AND_AND_8:
     case BUILT_IN_FETCH_AND_AND_2:
     case BUILT_IN_FETCH_AND_AND_4:
     case BUILT_IN_FETCH_AND_AND_8:
+    case BUILT_IN_FETCH_AND_AND_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
       target = expand_builtin_sync_operation (mode, arglist, AND,
                                              false, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
       target = expand_builtin_sync_operation (mode, arglist, AND,
                                              false, target, ignore);
@@ -6116,6 +6208,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_FETCH_AND_XOR_2:
     case BUILT_IN_FETCH_AND_XOR_4:
     case BUILT_IN_FETCH_AND_XOR_8:
     case BUILT_IN_FETCH_AND_XOR_2:
     case BUILT_IN_FETCH_AND_XOR_4:
     case BUILT_IN_FETCH_AND_XOR_8:
+    case BUILT_IN_FETCH_AND_XOR_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
       target = expand_builtin_sync_operation (mode, arglist, XOR,
                                              false, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
       target = expand_builtin_sync_operation (mode, arglist, XOR,
                                              false, target, ignore);
@@ -6127,6 +6220,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_FETCH_AND_NAND_2:
     case BUILT_IN_FETCH_AND_NAND_4:
     case BUILT_IN_FETCH_AND_NAND_8:
     case BUILT_IN_FETCH_AND_NAND_2:
     case BUILT_IN_FETCH_AND_NAND_4:
     case BUILT_IN_FETCH_AND_NAND_8:
+    case BUILT_IN_FETCH_AND_NAND_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
       target = expand_builtin_sync_operation (mode, arglist, NOT,
                                              false, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
       target = expand_builtin_sync_operation (mode, arglist, NOT,
                                              false, target, ignore);
@@ -6138,6 +6232,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_ADD_AND_FETCH_2:
     case BUILT_IN_ADD_AND_FETCH_4:
     case BUILT_IN_ADD_AND_FETCH_8:
     case BUILT_IN_ADD_AND_FETCH_2:
     case BUILT_IN_ADD_AND_FETCH_4:
     case BUILT_IN_ADD_AND_FETCH_8:
+    case BUILT_IN_ADD_AND_FETCH_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, PLUS,
                                              true, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, PLUS,
                                              true, target, ignore);
@@ -6149,6 +6244,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_SUB_AND_FETCH_2:
     case BUILT_IN_SUB_AND_FETCH_4:
     case BUILT_IN_SUB_AND_FETCH_8:
     case BUILT_IN_SUB_AND_FETCH_2:
     case BUILT_IN_SUB_AND_FETCH_4:
     case BUILT_IN_SUB_AND_FETCH_8:
+    case BUILT_IN_SUB_AND_FETCH_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, MINUS,
                                              true, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, MINUS,
                                              true, target, ignore);
@@ -6160,6 +6256,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_OR_AND_FETCH_2:
     case BUILT_IN_OR_AND_FETCH_4:
     case BUILT_IN_OR_AND_FETCH_8:
     case BUILT_IN_OR_AND_FETCH_2:
     case BUILT_IN_OR_AND_FETCH_4:
     case BUILT_IN_OR_AND_FETCH_8:
+    case BUILT_IN_OR_AND_FETCH_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, IOR,
                                              true, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, IOR,
                                              true, target, ignore);
@@ -6171,6 +6268,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_AND_AND_FETCH_2:
     case BUILT_IN_AND_AND_FETCH_4:
     case BUILT_IN_AND_AND_FETCH_8:
     case BUILT_IN_AND_AND_FETCH_2:
     case BUILT_IN_AND_AND_FETCH_4:
     case BUILT_IN_AND_AND_FETCH_8:
+    case BUILT_IN_AND_AND_FETCH_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, AND,
                                              true, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, AND,
                                              true, target, ignore);
@@ -6182,6 +6280,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_XOR_AND_FETCH_2:
     case BUILT_IN_XOR_AND_FETCH_4:
     case BUILT_IN_XOR_AND_FETCH_8:
     case BUILT_IN_XOR_AND_FETCH_2:
     case BUILT_IN_XOR_AND_FETCH_4:
     case BUILT_IN_XOR_AND_FETCH_8:
+    case BUILT_IN_XOR_AND_FETCH_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, XOR,
                                              true, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, XOR,
                                              true, target, ignore);
@@ -6193,6 +6292,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_NAND_AND_FETCH_2:
     case BUILT_IN_NAND_AND_FETCH_4:
     case BUILT_IN_NAND_AND_FETCH_8:
     case BUILT_IN_NAND_AND_FETCH_2:
     case BUILT_IN_NAND_AND_FETCH_4:
     case BUILT_IN_NAND_AND_FETCH_8:
+    case BUILT_IN_NAND_AND_FETCH_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, NOT,
                                              true, target, ignore);
       mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
       target = expand_builtin_sync_operation (mode, arglist, NOT,
                                              true, target, ignore);
@@ -6204,6 +6304,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
     case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
     case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
     case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
     case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
     case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
+    case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
       if (mode == VOIDmode)
        mode = TYPE_MODE (boolean_type_node);
       if (!target || !register_operand (target, mode))
       if (mode == VOIDmode)
        mode = TYPE_MODE (boolean_type_node);
       if (!target || !register_operand (target, mode))
@@ -6219,6 +6320,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
     case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
     case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
     case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
     case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
     case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
+    case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
       target = expand_builtin_compare_and_swap (mode, arglist, false, target);
       if (target)
       mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
       target = expand_builtin_compare_and_swap (mode, arglist, false, target);
       if (target)
@@ -6229,6 +6331,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_LOCK_TEST_AND_SET_2:
     case BUILT_IN_LOCK_TEST_AND_SET_4:
     case BUILT_IN_LOCK_TEST_AND_SET_8:
     case BUILT_IN_LOCK_TEST_AND_SET_2:
     case BUILT_IN_LOCK_TEST_AND_SET_4:
     case BUILT_IN_LOCK_TEST_AND_SET_8:
+    case BUILT_IN_LOCK_TEST_AND_SET_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
       target = expand_builtin_lock_test_and_set (mode, arglist, target);
       if (target)
       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
       target = expand_builtin_lock_test_and_set (mode, arglist, target);
       if (target)
@@ -6239,6 +6342,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_LOCK_RELEASE_2:
     case BUILT_IN_LOCK_RELEASE_4:
     case BUILT_IN_LOCK_RELEASE_8:
     case BUILT_IN_LOCK_RELEASE_2:
     case BUILT_IN_LOCK_RELEASE_4:
     case BUILT_IN_LOCK_RELEASE_8:
+    case BUILT_IN_LOCK_RELEASE_16:
       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
       expand_builtin_lock_release (mode, arglist);
       return const0_rtx;
       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
       expand_builtin_lock_release (mode, arglist);
       return const0_rtx;
@@ -6395,7 +6499,8 @@ fold_builtin_constant_p (tree arglist)
   if (TREE_SIDE_EFFECTS (arglist)
       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
       || POINTER_TYPE_P (TREE_TYPE (arglist))
   if (TREE_SIDE_EFFECTS (arglist)
       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
       || POINTER_TYPE_P (TREE_TYPE (arglist))
-      || cfun == 0)
+      || cfun == 0
+      || folding_initializer)
     return integer_zero_node;
 
   return 0;
     return integer_zero_node;
 
   return 0;
@@ -6551,7 +6656,7 @@ integer_valued_real_p (tree t)
     case REAL_CST:
       if (! TREE_CONSTANT_OVERFLOW (t))
       {
     case REAL_CST:
       if (! TREE_CONSTANT_OVERFLOW (t))
       {
-        REAL_VALUE_TYPE c, cint;
+       REAL_VALUE_TYPE c, cint;
 
        c = TREE_REAL_CST (t);
        real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
 
        c = TREE_REAL_CST (t);
        real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
@@ -6671,11 +6776,12 @@ fold_fixed_mathfn (tree fndecl, tree arglist)
 }
 
 /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
 }
 
 /* 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.  */
+   is the argument list, TYPE is the return type and FNDECL is the
+   original function DECL.  Return NULL_TREE if no if no simplification
+   can be made.  */
 
 static tree
 
 static tree
-fold_builtin_cabs (tree arglist, tree type)
+fold_builtin_cabs (tree arglist, tree type, tree fndecl)
 {
   tree arg;
 
 {
   tree arg;
 
@@ -6716,6 +6822,14 @@ fold_builtin_cabs (tree arglist, tree type)
       && real_zerop (TREE_OPERAND (arg, 1)))
     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
 
       && real_zerop (TREE_OPERAND (arg, 1)))
     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
 
+  /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z).  */
+  if (TREE_CODE (arg) == NEGATE_EXPR
+      || TREE_CODE (arg) == CONJ_EXPR)
+    {
+      tree arglist = build_tree_list (NULL_TREE, TREE_OPERAND (arg, 0));
+      return build_function_call_expr (fndecl, arglist);
+    }
+
   /* Don't do this when optimizing for size.  */
   if (flag_unsafe_math_optimizations
       && optimize && !optimize_size)
   /* Don't do this when optimizing for size.  */
   if (flag_unsafe_math_optimizations
       && optimize && !optimize_size)
@@ -6849,7 +6963,7 @@ fold_builtin_cbrt (tree arglist, tree type)
     {
       /* Optimize cbrt(expN(x)) -> expN(x/3).  */
       if (BUILTIN_EXPONENT_P (fcode))
     {
       /* Optimize cbrt(expN(x)) -> expN(x/3).  */
       if (BUILTIN_EXPONENT_P (fcode))
-        {
+       {
          tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
          const REAL_VALUE_TYPE third_trunc =
            real_value_truncate (TYPE_MODE (type), dconstthird);
          tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
          const REAL_VALUE_TYPE third_trunc =
            real_value_truncate (TYPE_MODE (type), dconstthird);
@@ -6862,7 +6976,7 @@ fold_builtin_cbrt (tree arglist, tree type)
 
       /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
       if (BUILTIN_SQRT_P (fcode))
 
       /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
       if (BUILTIN_SQRT_P (fcode))
-        {
+       {
          tree powfn = mathfn_built_in (type, BUILT_IN_POW);
 
          if (powfn)
          tree powfn = mathfn_built_in (type, BUILT_IN_POW);
 
          if (powfn)
@@ -6882,17 +6996,17 @@ fold_builtin_cbrt (tree arglist, tree type)
 
       /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
       if (BUILTIN_CBRT_P (fcode))
 
       /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
       if (BUILTIN_CBRT_P (fcode))
-        {
+       {
          tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
          if (tree_expr_nonnegative_p (arg0))
            {
              tree powfn = mathfn_built_in (type, BUILT_IN_POW);
 
              if (powfn)
          tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
          if (tree_expr_nonnegative_p (arg0))
            {
              tree powfn = mathfn_built_in (type, BUILT_IN_POW);
 
              if (powfn)
-               {
+               {
                  tree tree_root;
                  REAL_VALUE_TYPE dconstroot;
                  tree tree_root;
                  REAL_VALUE_TYPE dconstroot;
-             
+
                  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
                  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
                  tree_root = build_real (type, dconstroot);
                  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
                  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
                  tree_root = build_real (type, dconstroot);
@@ -6902,11 +7016,11 @@ fold_builtin_cbrt (tree arglist, tree type)
                }
            }
        }
                }
            }
        }
-      
+
       /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative.  */
       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
          || fcode == BUILT_IN_POWL)
       /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative.  */
       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
          || fcode == BUILT_IN_POWL)
-        {
+       {
          tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
          tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
          if (tree_expr_nonnegative_p (arg00))
          tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
          tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
          if (tree_expr_nonnegative_p (arg00))
@@ -7299,11 +7413,11 @@ real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
   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))));
+          && ! 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
 }
 
 /* A subroutine of fold_builtin to fold the various logarithmic
@@ -7325,10 +7439,10 @@ fold_builtin_logarithm (tree fndecl, tree arglist,
        return build_real (type, dconst0);
 
       /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
        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.  */
+        exactly, then only do this if flag_unsafe_math_optimizations.  */
       if (exact_real_truncate (TYPE_MODE (type), value)
          || 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))
          const REAL_VALUE_TYPE value_truncate =
            real_value_truncate (TYPE_MODE (type), *value);
          if (real_dconstp (arg, &value_truncate))
@@ -7349,10 +7463,10 @@ fold_builtin_logarithm (tree fndecl, tree arglist,
        return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
 
       /* Optimize logN(func()) for various exponential functions.  We
        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).  */
+        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)
       if (flag_unsafe_math_optimizations)
-        {
+       {
          tree exponent = 0, x = 0;
 
          switch (fcode)
          tree exponent = 0, x = 0;
 
          switch (fcode)
@@ -7497,7 +7611,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
 
       /* Optimize pow(expN(x),y) = expN(x*y).  */
       if (BUILTIN_EXPONENT_P (fcode))
 
       /* Optimize pow(expN(x),y) = expN(x*y).  */
       if (BUILTIN_EXPONENT_P (fcode))
-        {
+       {
          tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
          tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
          arg = fold_build2 (MULT_EXPR, type, arg, arg1);
          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);
@@ -7507,7 +7621,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
 
       /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
       if (BUILTIN_SQRT_P (fcode))
 
       /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
       if (BUILTIN_SQRT_P (fcode))
-        {
+       {
          tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
          tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
                                    build_real (type, dconsthalf));
          tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
          tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
                                    build_real (type, dconsthalf));
@@ -7519,7 +7633,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
 
       /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
       if (BUILTIN_CBRT_P (fcode))
 
       /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
       if (BUILTIN_CBRT_P (fcode))
-        {
+       {
          tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
          if (tree_expr_nonnegative_p (arg))
            {
          tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
          if (tree_expr_nonnegative_p (arg))
            {
@@ -7532,11 +7646,11 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
              return build_function_call_expr (fndecl, arglist);
            }
        }
              return build_function_call_expr (fndecl, arglist);
            }
        }
-      
+
       /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
           || fcode == BUILT_IN_POWL)
       /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
           || fcode == BUILT_IN_POWL)
-        {
+       {
          tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
          tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
          tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
          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);
@@ -7615,7 +7729,7 @@ fold_builtin_exponent (tree fndecl, tree arglist,
 
       /* Optimize expN(1.0) = N.  */
       if (real_onep (arg))
 
       /* Optimize expN(1.0) = N.  */
       if (real_onep (arg))
-        {
+       {
          REAL_VALUE_TYPE cst;
 
          real_convert (&cst, TYPE_MODE (type), value);
          REAL_VALUE_TYPE cst;
 
          real_convert (&cst, TYPE_MODE (type), value);
@@ -7626,7 +7740,7 @@ fold_builtin_exponent (tree fndecl, tree arglist,
       if (flag_unsafe_math_optimizations
          && TREE_CODE (arg) == REAL_CST
          && ! TREE_CONSTANT_OVERFLOW (arg))
       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;
          REAL_VALUE_TYPE cint;
          REAL_VALUE_TYPE c;
          HOST_WIDE_INT n;
@@ -7646,7 +7760,7 @@ fold_builtin_exponent (tree fndecl, tree arglist,
 
       /* Optimize expN(logN(x)) = x.  */
       if (flag_unsafe_math_optimizations)
 
       /* Optimize expN(logN(x)) = x.  */
       if (flag_unsafe_math_optimizations)
-        {
+       {
          const enum built_in_function fcode = builtin_mathfn_code (arg);
 
          if ((value == &dconste
          const enum built_in_function fcode = builtin_mathfn_code (arg);
 
          if ((value == &dconste
@@ -7714,14 +7828,14 @@ fold_builtin_mempcpy (tree arglist, tree type, int endp)
 
       /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
       if (operand_equal_p (src, dest, 0))
 
       /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
       if (operand_equal_p (src, dest, 0))
-        {
+       {
          if (endp == 0)
            return omit_one_operand (type, dest, len);
 
          if (endp == 2)
            len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
                               ssize_int (1));
          if (endp == 0)
            return omit_one_operand (type, dest, len);
 
          if (endp == 2)
            len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
                               ssize_int (1));
-      
+
          len = fold_convert (TREE_TYPE (dest), len);
          len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
          return fold_convert (type, len);
          len = fold_convert (TREE_TYPE (dest), len);
          len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
          return fold_convert (type, len);
@@ -8138,9 +8252,9 @@ fold_builtin_copysign (tree fndecl, tree arglist, tree type)
 
       c1 = TREE_REAL_CST (arg1);
       c2 = TREE_REAL_CST (arg2);
 
       c1 = TREE_REAL_CST (arg1);
       c2 = TREE_REAL_CST (arg2);
+      /* c1.sign := c2.sign.  */
       real_copysign (&c1, &c2);
       return build_real (type, c1);
       real_copysign (&c1, &c2);
       return build_real (type, c1);
-      c1.sign = c2.sign;
     }
 
   /* copysign(X, Y) is fabs(X) when Y is always non-negative.
     }
 
   /* copysign(X, Y) is fabs(X) when Y is always non-negative.
@@ -8180,9 +8294,9 @@ fold_builtin_isascii (tree arglist)
                         arg, integer_zero_node);
 
       if (in_gimple_form && !TREE_CONSTANT (arg))
                         arg, integer_zero_node);
 
       if (in_gimple_form && !TREE_CONSTANT (arg))
-        return NULL_TREE;
+       return NULL_TREE;
       else
       else
-        return arg;
+       return arg;
     }
 }
 
     }
 }
 
@@ -8228,9 +8342,9 @@ fold_builtin_isdigit (tree arglist)
       arg = fold_build2 (LE_EXPR, integer_type_node, arg,
                         build_int_cst (unsigned_type_node, 9));
       if (in_gimple_form && !TREE_CONSTANT (arg))
       arg = fold_build2 (LE_EXPR, integer_type_node, arg,
                         build_int_cst (unsigned_type_node, 9));
       if (in_gimple_form && !TREE_CONSTANT (arg))
-        return NULL_TREE;
+       return NULL_TREE;
       else
       else
-        return arg;
+       return arg;
     }
 }
 
     }
 }
 
@@ -8306,7 +8420,7 @@ fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
     {
     case BUILT_IN_ISINF:
       if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
     {
     case BUILT_IN_ISINF:
       if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
-        return omit_one_operand (type, integer_zero_node, arg);
+       return omit_one_operand (type, integer_zero_node, arg);
 
       if (TREE_CODE (arg) == REAL_CST)
        {
 
       if (TREE_CODE (arg) == REAL_CST)
        {
@@ -8322,8 +8436,8 @@ fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
 
     case BUILT_IN_FINITE:
       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
 
     case BUILT_IN_FINITE:
       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
-          && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
-        return omit_one_operand (type, integer_zero_node, arg);
+         && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+       return omit_one_operand (type, integer_zero_node, arg);
 
       if (TREE_CODE (arg) == REAL_CST)
        {
 
       if (TREE_CODE (arg) == REAL_CST)
        {
@@ -8336,7 +8450,7 @@ fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
 
     case BUILT_IN_ISNAN:
       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
 
     case BUILT_IN_ISNAN:
       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
-        return omit_one_operand (type, integer_zero_node, arg);
+       return omit_one_operand (type, integer_zero_node, arg);
 
       if (TREE_CODE (arg) == REAL_CST)
        {
 
       if (TREE_CODE (arg) == REAL_CST)
        {
@@ -8391,13 +8505,13 @@ fold_builtin_unordered_cmp (tree fndecl, tree arglist,
 
   arg0 = TREE_VALUE (arglist);
   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
 
   arg0 = TREE_VALUE (arglist);
   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  
+
   type0 = TREE_TYPE (arg0);
   type1 = TREE_TYPE (arg1);
   type0 = TREE_TYPE (arg0);
   type1 = TREE_TYPE (arg1);
-  
+
   code0 = TREE_CODE (type0);
   code1 = TREE_CODE (type1);
   code0 = TREE_CODE (type0);
   code1 = TREE_CODE (type1);
-  
+
   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
     /* Choose the wider of two real types.  */
     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
     /* Choose the wider of two real types.  */
     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
@@ -8412,7 +8526,7 @@ fold_builtin_unordered_cmp (tree fndecl, tree arglist,
                 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
       return error_mark_node;
     }
                 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
       return error_mark_node;
     }
-  
+
   arg0 = fold_convert (cmp_type, arg0);
   arg1 = fold_convert (cmp_type, arg1);
 
   arg0 = fold_convert (cmp_type, arg0);
   arg1 = fold_convert (cmp_type, arg1);
 
@@ -8536,18 +8650,18 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
 
     CASE_FLT_FN (BUILT_IN_CREAL):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
 
     CASE_FLT_FN (BUILT_IN_CREAL):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
-        return non_lvalue (fold_build1 (REALPART_EXPR, type,
+       return non_lvalue (fold_build1 (REALPART_EXPR, type,
                                        TREE_VALUE (arglist)));
       break;
 
     CASE_FLT_FN (BUILT_IN_CIMAG):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
                                        TREE_VALUE (arglist)));
       break;
 
     CASE_FLT_FN (BUILT_IN_CIMAG):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
-        return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
+       return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
                                        TREE_VALUE (arglist)));
       break;
 
     CASE_FLT_FN (BUILT_IN_CABS):
                                        TREE_VALUE (arglist)));
       break;
 
     CASE_FLT_FN (BUILT_IN_CABS):
-      return fold_builtin_cabs (arglist, type);
+      return fold_builtin_cabs (arglist, type, fndecl);
 
     CASE_FLT_FN (BUILT_IN_SQRT):
       return fold_builtin_sqrt (arglist, type);
 
     CASE_FLT_FN (BUILT_IN_SQRT):
       return fold_builtin_sqrt (arglist, type);
@@ -8593,12 +8707,18 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
       return fold_builtin_powi (fndecl, arglist, type);
 
     CASE_FLT_FN (BUILT_IN_INF):
       return fold_builtin_powi (fndecl, arglist, type);
 
     CASE_FLT_FN (BUILT_IN_INF):
+    case BUILT_IN_INFD32:
+    case BUILT_IN_INFD64:
+    case BUILT_IN_INFD128:
       return fold_builtin_inf (type, true);
 
     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
       return fold_builtin_inf (type, false);
 
     CASE_FLT_FN (BUILT_IN_NAN):
       return fold_builtin_inf (type, true);
 
     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
       return fold_builtin_inf (type, false);
 
     CASE_FLT_FN (BUILT_IN_NAN):
+    case BUILT_IN_NAND32:
+    case BUILT_IN_NAND64:
+    case BUILT_IN_NAND128:
       return fold_builtin_nan (arglist, type, true);
 
     CASE_FLT_FN (BUILT_IN_NANS):
       return fold_builtin_nan (arglist, type, true);
 
     CASE_FLT_FN (BUILT_IN_NANS):
@@ -8624,7 +8744,7 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     CASE_FLT_FN (BUILT_IN_LLCEIL):
     CASE_FLT_FN (BUILT_IN_LFLOOR):
     CASE_FLT_FN (BUILT_IN_LLFLOOR):
     CASE_FLT_FN (BUILT_IN_LLCEIL):
     CASE_FLT_FN (BUILT_IN_LFLOOR):
     CASE_FLT_FN (BUILT_IN_LLFLOOR):
-    CASE_FLT_FN (BUILT_IN_LROUND):   
+    CASE_FLT_FN (BUILT_IN_LROUND):
     CASE_FLT_FN (BUILT_IN_LLROUND):
       return fold_builtin_int_roundingfn (fndecl, arglist);
 
     CASE_FLT_FN (BUILT_IN_LLROUND):
       return fold_builtin_int_roundingfn (fndecl, arglist);
 
@@ -8664,12 +8784,21 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
       return fold_builtin_copysign (fndecl, arglist, type);
 
     CASE_FLT_FN (BUILT_IN_FINITE):
       return fold_builtin_copysign (fndecl, arglist, type);
 
     CASE_FLT_FN (BUILT_IN_FINITE):
+    case BUILT_IN_FINITED32:
+    case BUILT_IN_FINITED64:
+    case BUILT_IN_FINITED128:
       return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
 
     CASE_FLT_FN (BUILT_IN_ISINF):
       return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
 
     CASE_FLT_FN (BUILT_IN_ISINF):
+    case BUILT_IN_ISINFD32:
+    case BUILT_IN_ISINFD64:
+    case BUILT_IN_ISINFD128:
       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
 
     CASE_FLT_FN (BUILT_IN_ISNAN):
       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
 
     CASE_FLT_FN (BUILT_IN_ISNAN):
+    case BUILT_IN_ISNAND32:
+    case BUILT_IN_ISNAND64:
+    case BUILT_IN_ISNAND128:
       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
 
     case BUILT_IN_ISGREATER:
       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
 
     case BUILT_IN_ISGREATER:
@@ -9184,10 +9313,10 @@ fold_builtin_strncat (tree arglist)
       /* If the requested length is zero, or the src parameter string
         length is zero, return the dst parameter.  */
       if (integer_zerop (len) || (p && *p == '\0'))
       /* If the requested length is zero, or the src parameter string
         length is zero, return the dst parameter.  */
       if (integer_zerop (len) || (p && *p == '\0'))
-        return omit_two_operands (TREE_TYPE (dst), dst, src, len);
+       return omit_two_operands (TREE_TYPE (dst), dst, src, len);
 
       /* If the requested len is greater than or equal to the string
 
       /* If the requested len is greater than or equal to the string
-         length, call strcat.  */
+        length, call strcat.  */
       if (TREE_CODE (len) == INTEGER_CST && p
          && compare_tree_int (len, strlen (p)) >= 0)
        {
       if (TREE_CODE (len) == INTEGER_CST && p
          && compare_tree_int (len, strlen (p)) >= 0)
        {
@@ -9425,18 +9554,18 @@ fold_builtin_next_arg (tree arglist)
   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
      when we checked the arguments and if needed issued a warning.  */
   else if (!TREE_CHAIN (arglist)
   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
      when we checked the arguments and if needed issued a warning.  */
   else if (!TREE_CHAIN (arglist)
-           || !integer_zerop (TREE_VALUE (arglist))
-           || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
-           || TREE_CHAIN (TREE_CHAIN (arglist)))
+          || !integer_zerop (TREE_VALUE (arglist))
+          || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
+          || TREE_CHAIN (TREE_CHAIN (arglist)))
     {
       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
       tree arg = TREE_VALUE (arglist);
 
       if (TREE_CHAIN (arglist))
     {
       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
       tree arg = TREE_VALUE (arglist);
 
       if (TREE_CHAIN (arglist))
-        {
-          error ("%<va_start%> used with too many arguments");
-          return true;
-        }
+       {
+         error ("%<va_start%> used with too many arguments");
+         return true;
+       }
 
       /* Strip off all nops for the sake of the comparison.  This
         is not quite the same as STRIP_NOPS.  It does more.
 
       /* Strip off all nops for the sake of the comparison.  This
         is not quite the same as STRIP_NOPS.  It does more.
@@ -9448,7 +9577,7 @@ fold_builtin_next_arg (tree arglist)
             || TREE_CODE (arg) == INDIRECT_REF)
        arg = TREE_OPERAND (arg, 0);
       if (arg != last_parm)
             || TREE_CODE (arg) == INDIRECT_REF)
        arg = TREE_OPERAND (arg, 0);
       if (arg != last_parm)
-        {
+       {
          /* FIXME: Sometimes with the tree optimizers we can get the
             not the last argument even though the user used the last
             argument.  We just warn and set the arg to be the last
          /* FIXME: Sometimes with the tree optimizers we can get the
             not the last argument even though the user used the last
             argument.  We just warn and set the arg to be the last
@@ -9457,10 +9586,10 @@ fold_builtin_next_arg (tree arglist)
          warning (0, "second parameter of %<va_start%> not last named argument");
        }
       /* We want to verify the second parameter just once before the tree
          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,
-         as otherwise we could warn even for correct code like:
-         void foo (int i, ...)
-         { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
+        optimizers are run and then avoid keeping it in the tree,
+        as otherwise we could warn even for correct code like:
+        void foo (int i, ...)
+        { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
       TREE_VALUE (arglist) = integer_zero_node;
       TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
     }
       TREE_VALUE (arglist) = integer_zero_node;
       TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
     }
@@ -9544,7 +9673,7 @@ fold_builtin_sprintf (tree arglist, int ignored)
 
   if (call && retval)
     {
 
   if (call && retval)
     {
-      retval = convert
+      retval = fold_convert
        (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
         retval);
       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
        (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
         retval);
       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
@@ -10031,7 +10160,7 @@ fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
   /* If SRC and DEST are the same (and not volatile), return DEST.  */
   if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
     return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
   /* If SRC and DEST are the same (and not volatile), return DEST.  */
   if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
     return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
+
   if (! host_integerp (size, 1))
     return 0;
 
   if (! host_integerp (size, 1))
     return 0;
 
@@ -10492,7 +10621,7 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
 
   if (!init_target_chars())
     return 0;
 
   if (!init_target_chars())
     return 0;
-  
+
   if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
     {
       const char *str;
   if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
     {
       const char *str;
@@ -10653,7 +10782,7 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
 
   if (!init_target_chars())
     return 0;
 
   if (!init_target_chars())
     return 0;
-  
+
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
     {
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
     {
@@ -10745,7 +10874,7 @@ init_target_chars (void)
       target_percent_s_newline[1] = target_s;
       target_percent_s_newline[2] = target_newline;
       target_percent_s_newline[3] = '\0';
       target_percent_s_newline[1] = target_s;
       target_percent_s_newline[2] = target_newline;
       target_percent_s_newline[3] = '\0';
-      
+
       init = true;
     }
   return true;
       init = true;
     }
   return true;