OSDN Git Service

PR target/25168
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index da8c1d4..657f38b 100644 (file)
@@ -95,6 +95,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_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);
@@ -199,6 +200,15 @@ static tree fold_builtin_strncat_chk (tree, tree);
 static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
 static tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
 static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
+static bool init_target_chars (void);
+
+static unsigned HOST_WIDE_INT target_newline;
+static unsigned HOST_WIDE_INT target_percent;
+static unsigned HOST_WIDE_INT target_c;
+static unsigned HOST_WIDE_INT target_s;
+static char target_percent_c[3];
+static char target_percent_s[3];
+static char target_percent_s_newline[4];
 
 /* Return true if NODE should be considered for inline expansion regardless
    of the optimization level.  This means whenever a function is invoked with
@@ -529,8 +539,7 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
       tem = DYNAMIC_CHAIN_ADDRESS (tem);
 #endif
       tem = memory_address (Pmode, tem);
-      tem = gen_rtx_MEM (Pmode, tem);
-      set_mem_alias_set (tem, get_frame_alias_set ());
+      tem = gen_frame_mem (Pmode, tem);
       tem = copy_to_reg (tem);
     }
 
@@ -545,8 +554,7 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
 #else
   tem = memory_address (Pmode,
                        plus_constant (tem, GET_MODE_SIZE (Pmode)));
-  tem = gen_rtx_MEM (Pmode, tem);
-  set_mem_alias_set (tem, get_frame_alias_set ());
+  tem = gen_frame_mem (Pmode, tem);
 #endif
   return tem;
 }
@@ -1783,101 +1791,53 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
-    case BUILT_IN_SQRT:
-    case BUILT_IN_SQRTF:
-    case BUILT_IN_SQRTL:
+    CASE_FLT_FN (BUILT_IN_SQRT):
       errno_set = ! tree_expr_nonnegative_p (arg);
       builtin_optab = sqrt_optab;
       break;
-    case BUILT_IN_EXP:
-    case BUILT_IN_EXPF:
-    case BUILT_IN_EXPL:
+    CASE_FLT_FN (BUILT_IN_EXP):
       errno_set = true; builtin_optab = exp_optab; break;
-    case BUILT_IN_EXP10:
-    case BUILT_IN_EXP10F:
-    case BUILT_IN_EXP10L:
-    case BUILT_IN_POW10:
-    case BUILT_IN_POW10F:
-    case BUILT_IN_POW10L:
+    CASE_FLT_FN (BUILT_IN_EXP10):
+    CASE_FLT_FN (BUILT_IN_POW10):
       errno_set = true; builtin_optab = exp10_optab; break;
-    case BUILT_IN_EXP2:
-    case BUILT_IN_EXP2F:
-    case BUILT_IN_EXP2L:
+    CASE_FLT_FN (BUILT_IN_EXP2):
       errno_set = true; builtin_optab = exp2_optab; break;
-    case BUILT_IN_EXPM1:
-    case BUILT_IN_EXPM1F:
-    case BUILT_IN_EXPM1L:
+    CASE_FLT_FN (BUILT_IN_EXPM1):
       errno_set = true; builtin_optab = expm1_optab; break;
-    case BUILT_IN_LOGB:
-    case BUILT_IN_LOGBF:
-    case BUILT_IN_LOGBL:
+    CASE_FLT_FN (BUILT_IN_LOGB):
       errno_set = true; builtin_optab = logb_optab; break;
-    case BUILT_IN_ILOGB:
-    case BUILT_IN_ILOGBF:
-    case BUILT_IN_ILOGBL:
+    CASE_FLT_FN (BUILT_IN_ILOGB):
       errno_set = true; builtin_optab = ilogb_optab; break;
-    case BUILT_IN_LOG:
-    case BUILT_IN_LOGF:
-    case BUILT_IN_LOGL:
+    CASE_FLT_FN (BUILT_IN_LOG):
       errno_set = true; builtin_optab = log_optab; break;
-    case BUILT_IN_LOG10:
-    case BUILT_IN_LOG10F:
-    case BUILT_IN_LOG10L:
+    CASE_FLT_FN (BUILT_IN_LOG10):
       errno_set = true; builtin_optab = log10_optab; break;
-    case BUILT_IN_LOG2:
-    case BUILT_IN_LOG2F:
-    case BUILT_IN_LOG2L:
+    CASE_FLT_FN (BUILT_IN_LOG2):
       errno_set = true; builtin_optab = log2_optab; break;
-    case BUILT_IN_LOG1P:
-    case BUILT_IN_LOG1PF:
-    case BUILT_IN_LOG1PL:
+    CASE_FLT_FN (BUILT_IN_LOG1P):
       errno_set = true; builtin_optab = log1p_optab; break;
-    case BUILT_IN_ASIN:
-    case BUILT_IN_ASINF:
-    case BUILT_IN_ASINL:
+    CASE_FLT_FN (BUILT_IN_ASIN):
       builtin_optab = asin_optab; break;
-    case BUILT_IN_ACOS:
-    case BUILT_IN_ACOSF:
-    case BUILT_IN_ACOSL:
+    CASE_FLT_FN (BUILT_IN_ACOS):
       builtin_optab = acos_optab; break;
-    case BUILT_IN_TAN:
-    case BUILT_IN_TANF:
-    case BUILT_IN_TANL:
+    CASE_FLT_FN (BUILT_IN_TAN):
       builtin_optab = tan_optab; break;
-    case BUILT_IN_ATAN:
-    case BUILT_IN_ATANF:
-    case BUILT_IN_ATANL:
+    CASE_FLT_FN (BUILT_IN_ATAN):
       builtin_optab = atan_optab; break;
-    case BUILT_IN_FLOOR:
-    case BUILT_IN_FLOORF:
-    case BUILT_IN_FLOORL:
+    CASE_FLT_FN (BUILT_IN_FLOOR):
       builtin_optab = floor_optab; break;
-    case BUILT_IN_CEIL:
-    case BUILT_IN_CEILF:
-    case BUILT_IN_CEILL:
+    CASE_FLT_FN (BUILT_IN_CEIL):
       builtin_optab = ceil_optab; break;
-    case BUILT_IN_TRUNC:
-    case BUILT_IN_TRUNCF:
-    case BUILT_IN_TRUNCL:
+    CASE_FLT_FN (BUILT_IN_TRUNC):
       builtin_optab = btrunc_optab; break;
-    case BUILT_IN_ROUND:
-    case BUILT_IN_ROUNDF:
-    case BUILT_IN_ROUNDL:
+    CASE_FLT_FN (BUILT_IN_ROUND):
       builtin_optab = round_optab; break;
-    case BUILT_IN_NEARBYINT:
-    case BUILT_IN_NEARBYINTF:
-    case BUILT_IN_NEARBYINTL:
+    CASE_FLT_FN (BUILT_IN_NEARBYINT):
       builtin_optab = nearbyint_optab; break;
-    case BUILT_IN_RINT:
-    case BUILT_IN_RINTF:
-    case BUILT_IN_RINTL:
+    CASE_FLT_FN (BUILT_IN_RINT):
       builtin_optab = rint_optab; break;
-    case BUILT_IN_LRINT:
-    case BUILT_IN_LRINTF:
-    case BUILT_IN_LRINTL:
-    case BUILT_IN_LLRINT:
-    case BUILT_IN_LLRINTF:
-    case BUILT_IN_LLRINTL:
+    CASE_FLT_FN (BUILT_IN_LRINT):
+    CASE_FLT_FN (BUILT_IN_LLRINT):
       builtin_optab = lrint_optab; break;
     default:
       gcc_unreachable ();
@@ -2010,25 +1970,15 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
-    case BUILT_IN_POW:
-    case BUILT_IN_POWF:
-    case BUILT_IN_POWL:
+    CASE_FLT_FN (BUILT_IN_POW):
       builtin_optab = pow_optab; break;
-    case BUILT_IN_ATAN2:
-    case BUILT_IN_ATAN2F:
-    case BUILT_IN_ATAN2L:
+    CASE_FLT_FN (BUILT_IN_ATAN2):
       builtin_optab = atan2_optab; break;
-    case BUILT_IN_LDEXP:
-    case BUILT_IN_LDEXPF:
-    case BUILT_IN_LDEXPL:
+    CASE_FLT_FN (BUILT_IN_LDEXP):
       builtin_optab = ldexp_optab; break;
-    case BUILT_IN_FMOD:
-    case BUILT_IN_FMODF:
-    case BUILT_IN_FMODL:
+    CASE_FLT_FN (BUILT_IN_FMOD):
       builtin_optab = fmod_optab; break;
-    case BUILT_IN_DREM:
-    case BUILT_IN_DREMF:
-    case BUILT_IN_DREML:
+    CASE_FLT_FN (BUILT_IN_DREM):
       builtin_optab = drem_optab; break;
     default:
       gcc_unreachable ();
@@ -2115,7 +2065,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;
-  bool errno_set = false;
   tree arg, narg;
 
   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -2125,12 +2074,8 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
-    case BUILT_IN_SIN:
-    case BUILT_IN_SINF:
-    case BUILT_IN_SINL:
-    case BUILT_IN_COS:
-    case BUILT_IN_COSF:
-    case BUILT_IN_COSL:
+    CASE_FLT_FN (BUILT_IN_SIN):
+    CASE_FLT_FN (BUILT_IN_COS):
       builtin_optab = sincos_optab; break;
     default:
       gcc_unreachable ();
@@ -2139,21 +2084,14 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   /* 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) {
     switch (DECL_FUNCTION_CODE (fndecl))
       {
-      case BUILT_IN_SIN:
-      case BUILT_IN_SINF:
-      case BUILT_IN_SINL:
+      CASE_FLT_FN (BUILT_IN_SIN):
        builtin_optab = sin_optab; break;
-      case BUILT_IN_COS:
-      case BUILT_IN_COSF:
-      case BUILT_IN_COSL:
+      CASE_FLT_FN (BUILT_IN_COS):
        builtin_optab = cos_optab; break;
       default:
        gcc_unreachable ();
@@ -2188,14 +2126,10 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
 
          switch (DECL_FUNCTION_CODE (fndecl))
            {
-           case BUILT_IN_SIN:
-           case BUILT_IN_SINF:
-           case BUILT_IN_SINL:
+           CASE_FLT_FN (BUILT_IN_SIN):
              result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
              break;
-           case BUILT_IN_COS:
-           case BUILT_IN_COSF:
-           case BUILT_IN_COSL:
+           CASE_FLT_FN (BUILT_IN_COS):
              result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
              break;
            default:
@@ -2210,9 +2144,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
 
       if (target != 0)
        {
-         if (errno_set)
-           expand_errno_check (exp, target);
-
          /* Output the entire sequence.  */
          insns = get_insns ();
          end_sequence ();
@@ -2231,6 +2162,55 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   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_expr (arg, NULL_RTX, VOIDmode, 0);
+  op1 = expand_expr (build_fold_indirect_ref (sinp), NULL_RTX, VOIDmode, 0);
+  op2 = expand_expr (build_fold_indirect_ref (cosp), NULL_RTX, VOIDmode, 0);
+
+  /* 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;
@@ -2256,22 +2236,14 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
-    case BUILT_IN_LCEIL:
-    case BUILT_IN_LCEILF:
-    case BUILT_IN_LCEILL:
-    case BUILT_IN_LLCEIL:
-    case BUILT_IN_LLCEILF:
-    case BUILT_IN_LLCEILL:
+    CASE_FLT_FN (BUILT_IN_LCEIL):
+    CASE_FLT_FN (BUILT_IN_LLCEIL):
       builtin_optab = lceil_optab;
       fallback_fn = BUILT_IN_CEIL;
       break;
 
-    case BUILT_IN_LFLOOR:
-    case BUILT_IN_LFLOORF:
-    case BUILT_IN_LFLOORL:
-    case BUILT_IN_LLFLOOR:
-    case BUILT_IN_LLFLOORF:
-    case BUILT_IN_LLFLOORL:
+    CASE_FLT_FN (BUILT_IN_LFLOOR):
+    CASE_FLT_FN (BUILT_IN_LLFLOOR):
       builtin_optab = lfloor_optab;
       fallback_fn = BUILT_IN_FLOOR;
       break;
@@ -4233,7 +4205,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.  */
-  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,
@@ -4753,7 +4726,7 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
   return ret;
 }
 
-static void
+void
 expand_builtin_trap (void)
 {
 #ifdef HAVE_trap
@@ -4845,11 +4818,12 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
                       bool unlocked)
 {
   tree arglist = TREE_OPERAND (exp, 1);
-  tree fn_putchar = unlocked
-                   ? implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
-                   : implicit_built_in_decls[BUILT_IN_PUTCHAR];
-  tree fn_puts = unlocked ? implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED]
-                         : implicit_built_in_decls[BUILT_IN_PUTS];
+  /* If we're using an unlocked function, assume the other unlocked
+     functions exist explicitly.  */
+  tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
+    : implicit_built_in_decls[BUILT_IN_PUTCHAR];
+  tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
+    : implicit_built_in_decls[BUILT_IN_PUTS];
   const char *fmt_str;
   tree fn, fmt, arg;
 
@@ -4870,8 +4844,11 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
   if (fmt_str == NULL)
     return 0;
 
+  if (!init_target_chars())
+    return 0;
+  
   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
-  if (strcmp (fmt_str, "%s\n") == 0)
+  if (strcmp (fmt_str, target_percent_s_newline) == 0)
     {
       if (! arglist
           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
@@ -4880,7 +4857,7 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
       fn = fn_puts;
     }
   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
-  else if (strcmp (fmt_str, "%c") == 0)
+  else if (strcmp (fmt_str, target_percent_c) == 0)
     {
       if (! arglist
          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -4891,7 +4868,7 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
   else
     {
       /* We can't handle anything else with % args or %% ... yet.  */
-      if (strchr (fmt_str, '%'))
+      if (strchr (fmt_str, target_percent))
         return 0;
 
       if (arglist)
@@ -4914,7 +4891,7 @@ expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
        {
          /* If the format specifier was "string\n", call puts("string").  */
          size_t len = strlen (fmt_str);
-         if (fmt_str[len - 1] == '\n')
+         if ((unsigned char)fmt_str[len - 1] == target_newline)
            {
              /* Create a NUL-terminated string that's one char shorter
                 than the original, stripping off the trailing '\n'.  */
@@ -4951,10 +4928,12 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
                        bool unlocked)
 {
   tree arglist = TREE_OPERAND (exp, 1);
-  tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
-                          : implicit_built_in_decls[BUILT_IN_FPUTC];
-  tree fn_fputs = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
-                          : implicit_built_in_decls[BUILT_IN_FPUTS];
+  /* If we're using an unlocked function, assume the other unlocked
+     functions exist explicitly.  */
+  tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
+    : implicit_built_in_decls[BUILT_IN_FPUTC];
+  tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
+    : implicit_built_in_decls[BUILT_IN_FPUTS];
   const char *fmt_str;
   tree fn, fmt, fp, arg;
 
@@ -4981,8 +4960,11 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
   if (fmt_str == NULL)
     return 0;
 
+  if (!init_target_chars())
+    return 0;
+  
   /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
-  if (strcmp (fmt_str, "%s") == 0)
+  if (strcmp (fmt_str, target_percent_s) == 0)
     {
       if (! arglist
           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
@@ -4994,7 +4976,7 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
       fn = fn_fputs;
     }
   /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
-  else if (strcmp (fmt_str, "%c") == 0)
+  else if (strcmp (fmt_str, target_percent_c) == 0)
     {
       if (! arglist
          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -5008,7 +4990,7 @@ expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
   else
     {
       /* We can't handle anything else with % args or %% ... yet.  */
-      if (strchr (fmt_str, '%'))
+      if (strchr (fmt_str, target_percent))
         return 0;
 
       if (arglist)
@@ -5070,8 +5052,11 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
   if (fmt_str == NULL)
     return 0;
 
+  if (!init_target_chars())
+    return 0;
+
   /* If the format doesn't contain % args or %%, use strcpy.  */
-  if (strchr (fmt_str, '%') == 0)
+  if (strchr (fmt_str, target_percent) == 0)
     {
       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
       tree exp;
@@ -5086,7 +5071,7 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
       return expand_expr (exp, target, mode, EXPAND_NORMAL);
     }
   /* If the format is "%s", use strcpy if the result isn't used.  */
-  else if (strcmp (fmt_str, "%s") == 0)
+  else if (strcmp (fmt_str, target_percent_s) == 0)
     {
       tree fn, arg, len;
       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
@@ -5390,6 +5375,43 @@ expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
 }
 
 \f
+/* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
+   the pointer in these functions is void*, the tree optimizers may remove
+   casts.  The mode computed in expand_builtin isn't reliable either, due
+   to __sync_bool_compare_and_swap.
+
+   FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
+   group of builtins.  This gives us log2 of the mode size.  */
+
+static inline enum machine_mode
+get_builtin_sync_mode (int fcode_diff)
+{
+  /* The size is not negotiable, so ask not to get BLKmode in return
+     if the target indicates that a smaller size would be better.  */
+  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));
+  MEM_VOLATILE_P (mem) = 1;
+
+  return mem;
+}
+
 /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
    ARGLIST is the operands list to the function.  CODE is the rtx code 
    that corresponds to the arithmetic or logical operation from the name;
@@ -5399,25 +5421,18 @@ expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
    the result of the operation at all.  */
 
 static rtx
-expand_builtin_sync_operation (tree arglist, enum rtx_code code, bool after,
+expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
+                              enum rtx_code code, bool after,
                               rtx target, bool ignore)
 {
-  enum machine_mode mode;
-  rtx addr, val, mem;
+  rtx val, mem;
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
-  mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   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
@@ -5430,14 +5445,13 @@ expand_builtin_sync_operation (tree arglist, enum rtx_code code, bool after,
    results; this is NOT optional if IS_BOOL is true.  */
 
 static rtx
-expand_builtin_compare_and_swap (tree arglist, bool is_bool, rtx target)
+expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
+                                bool is_bool, rtx target)
 {
-  enum machine_mode mode;
-  rtx addr, old_val, new_val, mem;
+  rtx old_val, new_val, mem;
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
-  mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   arglist = TREE_CHAIN (arglist);
   old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
@@ -5445,12 +5459,6 @@ expand_builtin_compare_and_swap (tree arglist, bool is_bool, rtx target)
   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
@@ -5464,24 +5472,17 @@ expand_builtin_compare_and_swap (tree arglist, bool is_bool, rtx target)
    place for us to store the results.  */
 
 static rtx
-expand_builtin_lock_test_and_set (tree arglist, rtx target)
+expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
+                                 rtx target)
 {
-  enum machine_mode mode;
-  rtx addr, val, mem;
+  rtx val, mem;
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_NORMAL);
-  mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
+  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
 
   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);
 }
 
@@ -5490,7 +5491,7 @@ expand_builtin_lock_test_and_set (tree arglist, rtx target)
 static void
 expand_builtin_synchronize (void)
 {
-  rtx body;
+  tree x;
 
 #ifdef HAVE_memory_barrier
   if (HAVE_memory_barrier)
@@ -5500,33 +5501,26 @@ expand_builtin_synchronize (void)
     }
 #endif
 
-  /* If no explicit memory barrier instruction is available, create an empty
-     asm stmt that will prevent compiler movement across the barrier.  */
-  body = gen_rtx_ASM_INPUT (VOIDmode, "");
-  MEM_VOLATILE_P (body) = 1;
-  emit_insn (body);
+  /* If no explicit memory barrier instruction is available, create an
+     empty asm stmt with a memory clobber.  */
+  x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
+             tree_cons (NULL, build_string (6, "memory"), NULL));
+  ASM_VOLATILE_P (x) = 1;
+  expand_asm_expr (x);
 }
 
 /* Expand the __sync_lock_release intrinsic.  ARGLIST is the operands list
    to the function.  */
 
 static void
-expand_builtin_lock_release (tree arglist)
+expand_builtin_lock_release (enum machine_mode mode, tree arglist)
 {
-  enum machine_mode mode;
   enum insn_code icode;
-  rtx addr, val, mem, insn;
+  rtx mem, insn;
+  rtx val = const0_rtx;
 
   /* Expand the operands.  */
-  addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_NORMAL);
-  mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
-  val = const0_rtx;
-
-  /* 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];
@@ -5607,17 +5601,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
 
   switch (fcode)
     {
-    case BUILT_IN_FABS:
-    case BUILT_IN_FABSF:
-    case BUILT_IN_FABSL:
+    CASE_FLT_FN (BUILT_IN_FABS):
       target = expand_builtin_fabs (arglist, target, subtarget);
       if (target)
         return target;
       break;
 
-    case BUILT_IN_COPYSIGN:
-    case BUILT_IN_COPYSIGNF:
-    case BUILT_IN_COPYSIGNL:
+    CASE_FLT_FN (BUILT_IN_COPYSIGN):
       target = expand_builtin_copysign (arglist, target, subtarget);
       if (target)
        return target;
@@ -5625,137 +5615,67 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
 
       /* Just do a normal library call if we were unable to fold
         the values.  */
-    case BUILT_IN_CABS:
-    case BUILT_IN_CABSF:
-    case BUILT_IN_CABSL:
+    CASE_FLT_FN (BUILT_IN_CABS):
       break;
 
-    case BUILT_IN_EXP:
-    case BUILT_IN_EXPF:
-    case BUILT_IN_EXPL:
-    case BUILT_IN_EXP10:
-    case BUILT_IN_EXP10F:
-    case BUILT_IN_EXP10L:
-    case BUILT_IN_POW10:
-    case BUILT_IN_POW10F:
-    case BUILT_IN_POW10L:
-    case BUILT_IN_EXP2:
-    case BUILT_IN_EXP2F:
-    case BUILT_IN_EXP2L:
-    case BUILT_IN_EXPM1:
-    case BUILT_IN_EXPM1F:
-    case BUILT_IN_EXPM1L:
-    case BUILT_IN_LOGB:
-    case BUILT_IN_LOGBF:
-    case BUILT_IN_LOGBL:
-    case BUILT_IN_ILOGB:
-    case BUILT_IN_ILOGBF:
-    case BUILT_IN_ILOGBL:
-    case BUILT_IN_LOG:
-    case BUILT_IN_LOGF:
-    case BUILT_IN_LOGL:
-    case BUILT_IN_LOG10:
-    case BUILT_IN_LOG10F:
-    case BUILT_IN_LOG10L:
-    case BUILT_IN_LOG2:
-    case BUILT_IN_LOG2F:
-    case BUILT_IN_LOG2L:
-    case BUILT_IN_LOG1P:
-    case BUILT_IN_LOG1PF:
-    case BUILT_IN_LOG1PL:
-    case BUILT_IN_TAN:
-    case BUILT_IN_TANF:
-    case BUILT_IN_TANL:
-    case BUILT_IN_ASIN:
-    case BUILT_IN_ASINF:
-    case BUILT_IN_ASINL:
-    case BUILT_IN_ACOS:
-    case BUILT_IN_ACOSF:
-    case BUILT_IN_ACOSL:
-    case BUILT_IN_ATAN:
-    case BUILT_IN_ATANF:
-    case BUILT_IN_ATANL:
+    CASE_FLT_FN (BUILT_IN_EXP):
+    CASE_FLT_FN (BUILT_IN_EXP10):
+    CASE_FLT_FN (BUILT_IN_POW10):
+    CASE_FLT_FN (BUILT_IN_EXP2):
+    CASE_FLT_FN (BUILT_IN_EXPM1):
+    CASE_FLT_FN (BUILT_IN_LOGB):
+    CASE_FLT_FN (BUILT_IN_ILOGB):
+    CASE_FLT_FN (BUILT_IN_LOG):
+    CASE_FLT_FN (BUILT_IN_LOG10):
+    CASE_FLT_FN (BUILT_IN_LOG2):
+    CASE_FLT_FN (BUILT_IN_LOG1P):
+    CASE_FLT_FN (BUILT_IN_TAN):
+    CASE_FLT_FN (BUILT_IN_ASIN):
+    CASE_FLT_FN (BUILT_IN_ACOS):
+    CASE_FLT_FN (BUILT_IN_ATAN):
       /* Treat these like sqrt only if unsafe math optimizations are allowed,
         because of possible accuracy problems.  */
       if (! flag_unsafe_math_optimizations)
        break;
-    case BUILT_IN_SQRT:
-    case BUILT_IN_SQRTF:
-    case BUILT_IN_SQRTL:
-    case BUILT_IN_FLOOR:
-    case BUILT_IN_FLOORF:
-    case BUILT_IN_FLOORL:
-    case BUILT_IN_CEIL:
-    case BUILT_IN_CEILF:
-    case BUILT_IN_CEILL:
-    case BUILT_IN_TRUNC:
-    case BUILT_IN_TRUNCF:
-    case BUILT_IN_TRUNCL:
-    case BUILT_IN_ROUND:
-    case BUILT_IN_ROUNDF:
-    case BUILT_IN_ROUNDL:
-    case BUILT_IN_NEARBYINT:
-    case BUILT_IN_NEARBYINTF:
-    case BUILT_IN_NEARBYINTL:
-    case BUILT_IN_RINT:
-    case BUILT_IN_RINTF:
-    case BUILT_IN_RINTL:
-    case BUILT_IN_LRINT:
-    case BUILT_IN_LRINTF:
-    case BUILT_IN_LRINTL:
-    case BUILT_IN_LLRINT:
-    case BUILT_IN_LLRINTF:
-    case BUILT_IN_LLRINTL:
+    CASE_FLT_FN (BUILT_IN_SQRT):
+    CASE_FLT_FN (BUILT_IN_FLOOR):
+    CASE_FLT_FN (BUILT_IN_CEIL):
+    CASE_FLT_FN (BUILT_IN_TRUNC):
+    CASE_FLT_FN (BUILT_IN_ROUND):
+    CASE_FLT_FN (BUILT_IN_NEARBYINT):
+    CASE_FLT_FN (BUILT_IN_RINT):
+    CASE_FLT_FN (BUILT_IN_LRINT):
+    CASE_FLT_FN (BUILT_IN_LLRINT):
       target = expand_builtin_mathfn (exp, target, subtarget);
       if (target)
        return target;
       break;
 
-    case BUILT_IN_LCEIL:
-    case BUILT_IN_LCEILF:
-    case BUILT_IN_LCEILL:
-    case BUILT_IN_LLCEIL:
-    case BUILT_IN_LLCEILF:
-    case BUILT_IN_LLCEILL:
-    case BUILT_IN_LFLOOR:
-    case BUILT_IN_LFLOORF:
-    case BUILT_IN_LFLOORL:
-    case BUILT_IN_LLFLOOR:
-    case BUILT_IN_LLFLOORF:
-    case BUILT_IN_LLFLOORL:
+    CASE_FLT_FN (BUILT_IN_LCEIL):
+    CASE_FLT_FN (BUILT_IN_LLCEIL):
+    CASE_FLT_FN (BUILT_IN_LFLOOR):
+    CASE_FLT_FN (BUILT_IN_LLFLOOR):
       target = expand_builtin_int_roundingfn (exp, target, subtarget);
       if (target)
        return target;
       break;
 
-    case BUILT_IN_POW:
-    case BUILT_IN_POWF:
-    case BUILT_IN_POWL:
+    CASE_FLT_FN (BUILT_IN_POW):
       target = expand_builtin_pow (exp, target, subtarget);
       if (target)
        return target;
       break;
 
-    case BUILT_IN_POWI:
-    case BUILT_IN_POWIF:
-    case BUILT_IN_POWIL:
+    CASE_FLT_FN (BUILT_IN_POWI):
       target = expand_builtin_powi (exp, target, subtarget);
       if (target)
        return target;
       break;
 
-    case BUILT_IN_ATAN2:
-    case BUILT_IN_ATAN2F:
-    case BUILT_IN_ATAN2L:
-    case BUILT_IN_LDEXP:
-    case BUILT_IN_LDEXPF:
-    case BUILT_IN_LDEXPL:
-    case BUILT_IN_FMOD:
-    case BUILT_IN_FMODF:
-    case BUILT_IN_FMODL:
-    case BUILT_IN_DREM:
-    case BUILT_IN_DREMF:
-    case BUILT_IN_DREML:
+    CASE_FLT_FN (BUILT_IN_ATAN2):
+    CASE_FLT_FN (BUILT_IN_LDEXP):
+    CASE_FLT_FN (BUILT_IN_FMOD):
+    CASE_FLT_FN (BUILT_IN_DREM):
       if (! flag_unsafe_math_optimizations)
        break;
       target = expand_builtin_mathfn_2 (exp, target, subtarget);
@@ -5763,12 +5683,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
-    case BUILT_IN_SIN:
-    case BUILT_IN_SINF:
-    case BUILT_IN_SINL:
-    case BUILT_IN_COS:
-    case BUILT_IN_COSF:
-    case BUILT_IN_COSL:
+    CASE_FLT_FN (BUILT_IN_SIN):
+    CASE_FLT_FN (BUILT_IN_COS):
       if (! flag_unsafe_math_optimizations)
        break;
       target = expand_builtin_mathfn_3 (exp, target, subtarget);
@@ -5776,6 +5692,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        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 ();
 
@@ -5861,9 +5785,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       expand_stack_restore (TREE_VALUE (arglist));
       return const0_rtx;
 
-    case BUILT_IN_FFS:
-    case BUILT_IN_FFSL:
-    case BUILT_IN_FFSLL:
+    CASE_INT_FN (BUILT_IN_FFS):
     case BUILT_IN_FFSIMAX:
       target = expand_builtin_unop (target_mode, arglist, target,
                                    subtarget, ffs_optab);
@@ -5871,9 +5793,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
-    case BUILT_IN_CLZ:
-    case BUILT_IN_CLZL:
-    case BUILT_IN_CLZLL:
+    CASE_INT_FN (BUILT_IN_CLZ):
     case BUILT_IN_CLZIMAX:
       target = expand_builtin_unop (target_mode, arglist, target,
                                    subtarget, clz_optab);
@@ -5881,9 +5801,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
-    case BUILT_IN_CTZ:
-    case BUILT_IN_CTZL:
-    case BUILT_IN_CTZLL:
+    CASE_INT_FN (BUILT_IN_CTZ):
     case BUILT_IN_CTZIMAX:
       target = expand_builtin_unop (target_mode, arglist, target,
                                    subtarget, ctz_optab);
@@ -5891,9 +5809,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
-    case BUILT_IN_POPCOUNT:
-    case BUILT_IN_POPCOUNTL:
-    case BUILT_IN_POPCOUNTLL:
+    CASE_INT_FN (BUILT_IN_POPCOUNT):
     case BUILT_IN_POPCOUNTIMAX:
       target = expand_builtin_unop (target_mode, arglist, target,
                                    subtarget, popcount_optab);
@@ -5901,9 +5817,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
-    case BUILT_IN_PARITY:
-    case BUILT_IN_PARITYL:
-    case BUILT_IN_PARITYLL:
+    CASE_INT_FN (BUILT_IN_PARITY):
     case BUILT_IN_PARITYIMAX:
       target = expand_builtin_unop (target_mode, arglist, target,
                                    subtarget, parity_optab);
@@ -6134,9 +6048,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
-    case BUILT_IN_SIGNBIT:
-    case BUILT_IN_SIGNBITF:
-    case BUILT_IN_SIGNBITL:
+    CASE_FLT_FN (BUILT_IN_SIGNBIT):
       target = expand_builtin_signbit (exp, target);
       if (target)
        return target;
@@ -6209,7 +6121,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, PLUS,
+    case BUILT_IN_FETCH_AND_ADD_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
+      target = expand_builtin_sync_operation (mode, arglist, PLUS,
                                              false, target, ignore);
       if (target)
        return target;
@@ -6219,7 +6133,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, MINUS,
+    case BUILT_IN_FETCH_AND_SUB_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
+      target = expand_builtin_sync_operation (mode, arglist, MINUS,
                                              false, target, ignore);
       if (target)
        return target;
@@ -6229,7 +6145,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, IOR,
+    case BUILT_IN_FETCH_AND_OR_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
+      target = expand_builtin_sync_operation (mode, arglist, IOR,
                                              false, target, ignore);
       if (target)
        return target;
@@ -6239,7 +6157,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, AND,
+    case BUILT_IN_FETCH_AND_AND_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
+      target = expand_builtin_sync_operation (mode, arglist, AND,
                                              false, target, ignore);
       if (target)
        return target;
@@ -6249,7 +6169,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, XOR,
+    case BUILT_IN_FETCH_AND_XOR_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
+      target = expand_builtin_sync_operation (mode, arglist, XOR,
                                              false, target, ignore);
       if (target)
        return target;
@@ -6259,7 +6181,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, NOT,
+    case BUILT_IN_FETCH_AND_NAND_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
+      target = expand_builtin_sync_operation (mode, arglist, NOT,
                                              false, target, ignore);
       if (target)
        return target;
@@ -6269,7 +6193,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, PLUS,
+    case BUILT_IN_ADD_AND_FETCH_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
+      target = expand_builtin_sync_operation (mode, arglist, PLUS,
                                              true, target, ignore);
       if (target)
        return target;
@@ -6279,7 +6205,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, MINUS,
+    case BUILT_IN_SUB_AND_FETCH_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
+      target = expand_builtin_sync_operation (mode, arglist, MINUS,
                                              true, target, ignore);
       if (target)
        return target;
@@ -6289,7 +6217,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, IOR,
+    case BUILT_IN_OR_AND_FETCH_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
+      target = expand_builtin_sync_operation (mode, arglist, IOR,
                                              true, target, ignore);
       if (target)
        return target;
@@ -6299,7 +6229,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, AND,
+    case BUILT_IN_AND_AND_FETCH_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
+      target = expand_builtin_sync_operation (mode, arglist, AND,
                                              true, target, ignore);
       if (target)
        return target;
@@ -6309,7 +6241,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, XOR,
+    case BUILT_IN_XOR_AND_FETCH_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
+      target = expand_builtin_sync_operation (mode, arglist, XOR,
                                              true, target, ignore);
       if (target)
        return target;
@@ -6319,7 +6253,9 @@ 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:
-      target = expand_builtin_sync_operation (arglist, NOT,
+    case BUILT_IN_NAND_AND_FETCH_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
+      target = expand_builtin_sync_operation (mode, arglist, NOT,
                                              true, target, ignore);
       if (target)
        return target;
@@ -6329,11 +6265,14 @@ 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_16:
       if (mode == VOIDmode)
        mode = TYPE_MODE (boolean_type_node);
       if (!target || !register_operand (target, mode))
        target = gen_reg_rtx (mode);
-      target = expand_builtin_compare_and_swap (arglist, true, target);
+
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
+      target = expand_builtin_compare_and_swap (mode, arglist, true, target);
       if (target)
        return target;
       break;
@@ -6342,7 +6281,9 @@ 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:
-      target = expand_builtin_compare_and_swap (arglist, false, target);
+    case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
+      target = expand_builtin_compare_and_swap (mode, arglist, false, target);
       if (target)
        return target;
       break;
@@ -6351,7 +6292,9 @@ 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:
-      target = expand_builtin_lock_test_and_set (arglist, target);
+    case BUILT_IN_LOCK_TEST_AND_SET_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
+      target = expand_builtin_lock_test_and_set (mode, arglist, target);
       if (target)
        return target;
       break;
@@ -6360,7 +6303,9 @@ 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:
-      expand_builtin_lock_release (arglist);
+    case BUILT_IN_LOCK_RELEASE_16:
+      mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
+      expand_builtin_lock_release (mode, arglist);
       return const0_rtx;
 
     case BUILT_IN_SYNCHRONIZE:
@@ -6677,6 +6622,7 @@ integer_valued_real_p (tree t)
        real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
        return real_identical (&c, &cint);
       }
+      break;
 
     case NOP_EXPR:
       {
@@ -6691,24 +6637,12 @@ integer_valued_real_p (tree t)
     case CALL_EXPR:
       switch (builtin_mathfn_code (t))
        {
-       case BUILT_IN_CEIL:
-       case BUILT_IN_CEILF:
-       case BUILT_IN_CEILL:
-       case BUILT_IN_FLOOR:
-       case BUILT_IN_FLOORF:
-       case BUILT_IN_FLOORL:
-       case BUILT_IN_NEARBYINT:
-       case BUILT_IN_NEARBYINTF:
-       case BUILT_IN_NEARBYINTL:
-       case BUILT_IN_RINT:
-       case BUILT_IN_RINTF:
-       case BUILT_IN_RINTL:
-       case BUILT_IN_ROUND:
-       case BUILT_IN_ROUNDF:
-       case BUILT_IN_ROUNDL:
-       case BUILT_IN_TRUNC:
-       case BUILT_IN_TRUNCF:
-       case BUILT_IN_TRUNCL:
+       CASE_FLT_FN (BUILT_IN_CEIL):
+       CASE_FLT_FN (BUILT_IN_FLOOR):
+       CASE_FLT_FN (BUILT_IN_NEARBYINT):
+       CASE_FLT_FN (BUILT_IN_RINT):
+       CASE_FLT_FN (BUILT_IN_ROUND):
+       CASE_FLT_FN (BUILT_IN_TRUNC):
          return true;
 
        default:
@@ -7299,30 +7233,18 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
 
          switch (DECL_FUNCTION_CODE (fndecl))
            {
-           case BUILT_IN_LFLOOR:
-           case BUILT_IN_LFLOORF:
-           case BUILT_IN_LFLOORL:
-           case BUILT_IN_LLFLOOR:
-           case BUILT_IN_LLFLOORF:
-           case BUILT_IN_LLFLOORL:
+           CASE_FLT_FN (BUILT_IN_LFLOOR):
+           CASE_FLT_FN (BUILT_IN_LLFLOOR):
              real_floor (&r, TYPE_MODE (ftype), &x);
              break;
 
-           case BUILT_IN_LCEIL:
-           case BUILT_IN_LCEILF:
-           case BUILT_IN_LCEILL:
-           case BUILT_IN_LLCEIL:
-           case BUILT_IN_LLCEILF:
-           case BUILT_IN_LLCEILL:
+           CASE_FLT_FN (BUILT_IN_LCEIL):
+           CASE_FLT_FN (BUILT_IN_LLCEIL):
              real_ceil (&r, TYPE_MODE (ftype), &x);
              break;
 
-           case BUILT_IN_LROUND:
-           case BUILT_IN_LROUNDF:
-           case BUILT_IN_LROUNDL:
-           case BUILT_IN_LLROUND:
-           case BUILT_IN_LLROUNDF:
-           case BUILT_IN_LLROUNDL:
+           CASE_FLT_FN (BUILT_IN_LROUND):
+           CASE_FLT_FN (BUILT_IN_LLROUND):
              real_round (&r, TYPE_MODE (ftype), &x);
              break;
 
@@ -7380,9 +7302,7 @@ fold_builtin_bitop (tree fndecl, tree arglist)
 
       switch (DECL_FUNCTION_CODE (fndecl))
        {
-       case BUILT_IN_FFS:
-       case BUILT_IN_FFSL:
-       case BUILT_IN_FFSLL:
+       CASE_INT_FN (BUILT_IN_FFS):
          if (lo != 0)
            result = exact_log2 (lo & -lo) + 1;
          else if (hi != 0)
@@ -7391,9 +7311,7 @@ fold_builtin_bitop (tree fndecl, tree arglist)
            result = 0;
          break;
 
-       case BUILT_IN_CLZ:
-       case BUILT_IN_CLZL:
-       case BUILT_IN_CLZLL:
+       CASE_INT_FN (BUILT_IN_CLZ):
          if (hi != 0)
            result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
          else if (lo != 0)
@@ -7402,9 +7320,7 @@ fold_builtin_bitop (tree fndecl, tree arglist)
            result = width;
          break;
 
-       case BUILT_IN_CTZ:
-       case BUILT_IN_CTZL:
-       case BUILT_IN_CTZLL:
+       CASE_INT_FN (BUILT_IN_CTZ):
          if (lo != 0)
            result = exact_log2 (lo & -lo);
          else if (hi != 0)
@@ -7413,9 +7329,7 @@ fold_builtin_bitop (tree fndecl, tree arglist)
            result = width;
          break;
 
-       case BUILT_IN_POPCOUNT:
-       case BUILT_IN_POPCOUNTL:
-       case BUILT_IN_POPCOUNTLL:
+       CASE_INT_FN (BUILT_IN_POPCOUNT):
          result = 0;
          while (lo)
            result++, lo &= lo - 1;
@@ -7423,9 +7337,7 @@ fold_builtin_bitop (tree fndecl, tree arglist)
            result++, hi &= hi - 1;
          break;
 
-       case BUILT_IN_PARITY:
-       case BUILT_IN_PARITYL:
-       case BUILT_IN_PARITYLL:
+       CASE_INT_FN (BUILT_IN_PARITY):
          result = 0;
          while (lo)
            result++, lo &= lo - 1;
@@ -7510,49 +7422,35 @@ fold_builtin_logarithm (tree fndecl, tree arglist,
 
          switch (fcode)
          {
-         case BUILT_IN_EXP:
-         case BUILT_IN_EXPF:
-         case BUILT_IN_EXPL:
+         CASE_FLT_FN (BUILT_IN_EXP):
            /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
            x = build_real (type,
                            real_value_truncate (TYPE_MODE (type), dconste));
            exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
            break;
-         case BUILT_IN_EXP2:
-         case BUILT_IN_EXP2F:
-         case BUILT_IN_EXP2L:
+         CASE_FLT_FN (BUILT_IN_EXP2):
            /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
            x = build_real (type, dconst2);
            exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
            break;
-         case BUILT_IN_EXP10:
-         case BUILT_IN_EXP10F:
-         case BUILT_IN_EXP10L:
-         case BUILT_IN_POW10:
-         case BUILT_IN_POW10F:
-         case BUILT_IN_POW10L:
+         CASE_FLT_FN (BUILT_IN_EXP10):
+         CASE_FLT_FN (BUILT_IN_POW10):
            /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
            x = build_real (type, dconst10);
            exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
            break;
-         case BUILT_IN_SQRT:
-         case BUILT_IN_SQRTF:
-         case BUILT_IN_SQRTL:
+         CASE_FLT_FN (BUILT_IN_SQRT):
            /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
            x = TREE_VALUE (TREE_OPERAND (arg, 1));
            exponent = build_real (type, dconsthalf);
            break;
-         case BUILT_IN_CBRT:
-         case BUILT_IN_CBRTF:
-         case BUILT_IN_CBRTL:
+         CASE_FLT_FN (BUILT_IN_CBRT):
            /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
            x = TREE_VALUE (TREE_OPERAND (arg, 1));
            exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
                                                              dconstthird));
            break;
-         case BUILT_IN_POW:
-         case BUILT_IN_POWF:
-         case BUILT_IN_POWL:
+         CASE_FLT_FN (BUILT_IN_POW):
            /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
            x = TREE_VALUE (TREE_OPERAND (arg, 1));
            exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
@@ -8065,7 +7963,9 @@ fold_builtin_memcmp (tree arglist)
   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
-      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
+      tree cst_uchar_ptr_node
+       = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
       tree ind1 = fold_convert (integer_type_node,
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
@@ -8117,7 +8017,9 @@ fold_builtin_strcmp (tree arglist)
   if (p2 && *p2 == '\0')
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
-      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
+      tree cst_uchar_ptr_node
+       = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
       return fold_convert (integer_type_node,
                           build1 (INDIRECT_REF, cst_uchar_node,
                                   fold_convert (cst_uchar_ptr_node,
@@ -8128,7 +8030,9 @@ fold_builtin_strcmp (tree arglist)
   if (p1 && *p1 == '\0')
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
-      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
+      tree cst_uchar_ptr_node
+       = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
       tree temp = fold_convert (integer_type_node,
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
@@ -8186,7 +8090,9 @@ fold_builtin_strncmp (tree arglist)
       && tree_int_cst_sgn (len) == 1)
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
-      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
+      tree cst_uchar_ptr_node
+       = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
       return fold_convert (integer_type_node,
                           build1 (INDIRECT_REF, cst_uchar_node,
                                   fold_convert (cst_uchar_ptr_node,
@@ -8200,7 +8106,9 @@ fold_builtin_strncmp (tree arglist)
       && tree_int_cst_sgn (len) == 1)
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
-      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
+      tree cst_uchar_ptr_node
+       = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
       tree temp = fold_convert (integer_type_node,
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
@@ -8213,7 +8121,9 @@ fold_builtin_strncmp (tree arglist)
   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
-      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
+      tree cst_uchar_ptr_node
+       = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
       tree ind1 = fold_convert (integer_type_node,
                                build1 (INDIRECT_REF, cst_uchar_node,
                                        fold_convert (cst_uchar_ptr_node,
@@ -8675,9 +8585,7 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     case BUILT_IN_STRLEN:
       return fold_builtin_strlen (arglist);
 
-    case BUILT_IN_FABS:
-    case BUILT_IN_FABSF:
-    case BUILT_IN_FABSL:
+    CASE_FLT_FN (BUILT_IN_FABS):
       return fold_builtin_fabs (arglist, type);
 
     case BUILT_IN_ABS:
@@ -8686,198 +8594,120 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     case BUILT_IN_IMAXABS:
       return fold_builtin_abs (arglist, type);
 
-    case BUILT_IN_CONJ:
-    case BUILT_IN_CONJF:
-    case BUILT_IN_CONJL:
+    CASE_FLT_FN (BUILT_IN_CONJ):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
        return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
       break;
 
-    case BUILT_IN_CREAL:
-    case BUILT_IN_CREALF:
-    case BUILT_IN_CREALL:
+    CASE_FLT_FN (BUILT_IN_CREAL):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
         return non_lvalue (fold_build1 (REALPART_EXPR, type,
                                        TREE_VALUE (arglist)));
       break;
 
-    case BUILT_IN_CIMAG:
-    case BUILT_IN_CIMAGF:
-    case BUILT_IN_CIMAGL:
+    CASE_FLT_FN (BUILT_IN_CIMAG):
       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
         return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
                                        TREE_VALUE (arglist)));
       break;
 
-    case BUILT_IN_CABS:
-    case BUILT_IN_CABSF:
-    case BUILT_IN_CABSL:
+    CASE_FLT_FN (BUILT_IN_CABS):
       return fold_builtin_cabs (arglist, type);
 
-    case BUILT_IN_SQRT:
-    case BUILT_IN_SQRTF:
-    case BUILT_IN_SQRTL:
+    CASE_FLT_FN (BUILT_IN_SQRT):
       return fold_builtin_sqrt (arglist, type);
 
-    case BUILT_IN_CBRT:
-    case BUILT_IN_CBRTF:
-    case BUILT_IN_CBRTL:
+    CASE_FLT_FN (BUILT_IN_CBRT):
       return fold_builtin_cbrt (arglist, type);
 
-    case BUILT_IN_SIN:
-    case BUILT_IN_SINF:
-    case BUILT_IN_SINL:
+    CASE_FLT_FN (BUILT_IN_SIN):
       return fold_builtin_sin (arglist);
 
-    case BUILT_IN_COS:
-    case BUILT_IN_COSF:
-    case BUILT_IN_COSL:
+    CASE_FLT_FN (BUILT_IN_COS):
       return fold_builtin_cos (arglist, type, fndecl);
 
-    case BUILT_IN_EXP:
-    case BUILT_IN_EXPF:
-    case BUILT_IN_EXPL:
+    CASE_FLT_FN (BUILT_IN_EXP):
       return fold_builtin_exponent (fndecl, arglist, &dconste);
 
-    case BUILT_IN_EXP2:
-    case BUILT_IN_EXP2F:
-    case BUILT_IN_EXP2L:
+    CASE_FLT_FN (BUILT_IN_EXP2):
       return fold_builtin_exponent (fndecl, arglist, &dconst2);
 
-    case BUILT_IN_EXP10:
-    case BUILT_IN_EXP10F:
-    case BUILT_IN_EXP10L:
-    case BUILT_IN_POW10:
-    case BUILT_IN_POW10F:
-    case BUILT_IN_POW10L:
+    CASE_FLT_FN (BUILT_IN_EXP10):
+    CASE_FLT_FN (BUILT_IN_POW10):
       return fold_builtin_exponent (fndecl, arglist, &dconst10);
 
-    case BUILT_IN_LOG:
-    case BUILT_IN_LOGF:
-    case BUILT_IN_LOGL:
+    CASE_FLT_FN (BUILT_IN_LOG):
       return fold_builtin_logarithm (fndecl, arglist, &dconste);
 
-    case BUILT_IN_LOG2:
-    case BUILT_IN_LOG2F:
-    case BUILT_IN_LOG2L:
+    CASE_FLT_FN (BUILT_IN_LOG2):
       return fold_builtin_logarithm (fndecl, arglist, &dconst2);
 
-    case BUILT_IN_LOG10:
-    case BUILT_IN_LOG10F:
-    case BUILT_IN_LOG10L:
+    CASE_FLT_FN (BUILT_IN_LOG10):
       return fold_builtin_logarithm (fndecl, arglist, &dconst10);
 
-    case BUILT_IN_TAN:
-    case BUILT_IN_TANF:
-    case BUILT_IN_TANL:
+    CASE_FLT_FN (BUILT_IN_TAN):
       return fold_builtin_tan (arglist);
 
-    case BUILT_IN_ATAN:
-    case BUILT_IN_ATANF:
-    case BUILT_IN_ATANL:
+    CASE_FLT_FN (BUILT_IN_ATAN):
       return fold_builtin_atan (arglist, type);
 
-    case BUILT_IN_POW:
-    case BUILT_IN_POWF:
-    case BUILT_IN_POWL:
+    CASE_FLT_FN (BUILT_IN_POW):
       return fold_builtin_pow (fndecl, arglist, type);
 
-    case BUILT_IN_POWI:
-    case BUILT_IN_POWIF:
-    case BUILT_IN_POWIL:
+    CASE_FLT_FN (BUILT_IN_POWI):
       return fold_builtin_powi (fndecl, arglist, type);
 
-    case BUILT_IN_INF:
-    case BUILT_IN_INFF:
-    case BUILT_IN_INFL:
+    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 BUILT_IN_HUGE_VAL:
-    case BUILT_IN_HUGE_VALF:
-    case BUILT_IN_HUGE_VALL:
+    CASE_FLT_FN (BUILT_IN_HUGE_VAL):
       return fold_builtin_inf (type, false);
 
-    case BUILT_IN_NAN:
-    case BUILT_IN_NANF:
-    case BUILT_IN_NANL:
+    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 BUILT_IN_NANS:
-    case BUILT_IN_NANSF:
-    case BUILT_IN_NANSL:
+    CASE_FLT_FN (BUILT_IN_NANS):
       return fold_builtin_nan (arglist, type, false);
 
-    case BUILT_IN_FLOOR:
-    case BUILT_IN_FLOORF:
-    case BUILT_IN_FLOORL:
+    CASE_FLT_FN (BUILT_IN_FLOOR):
       return fold_builtin_floor (fndecl, arglist);
 
-    case BUILT_IN_CEIL:
-    case BUILT_IN_CEILF:
-    case BUILT_IN_CEILL:
+    CASE_FLT_FN (BUILT_IN_CEIL):
       return fold_builtin_ceil (fndecl, arglist);
 
-    case BUILT_IN_TRUNC:
-    case BUILT_IN_TRUNCF:
-    case BUILT_IN_TRUNCL:
+    CASE_FLT_FN (BUILT_IN_TRUNC):
       return fold_builtin_trunc (fndecl, arglist);
 
-    case BUILT_IN_ROUND:
-    case BUILT_IN_ROUNDF:
-    case BUILT_IN_ROUNDL:
+    CASE_FLT_FN (BUILT_IN_ROUND):
       return fold_builtin_round (fndecl, arglist);
 
-    case BUILT_IN_NEARBYINT:
-    case BUILT_IN_NEARBYINTF:
-    case BUILT_IN_NEARBYINTL:
-    case BUILT_IN_RINT:
-    case BUILT_IN_RINTF:
-    case BUILT_IN_RINTL:
+    CASE_FLT_FN (BUILT_IN_NEARBYINT):
+    CASE_FLT_FN (BUILT_IN_RINT):
       return fold_trunc_transparent_mathfn (fndecl, arglist);
 
-    case BUILT_IN_LCEIL:
-    case BUILT_IN_LCEILF:
-    case BUILT_IN_LCEILL:
-    case BUILT_IN_LLCEIL:
-    case BUILT_IN_LLCEILF:
-    case BUILT_IN_LLCEILL:
-    case BUILT_IN_LFLOOR:
-    case BUILT_IN_LFLOORF:
-    case BUILT_IN_LFLOORL:
-    case BUILT_IN_LLFLOOR:
-    case BUILT_IN_LLFLOORF:
-    case BUILT_IN_LLFLOORL:
-    case BUILT_IN_LROUND:
-    case BUILT_IN_LROUNDF:
-    case BUILT_IN_LROUNDL:
-    case BUILT_IN_LLROUND:
-    case BUILT_IN_LLROUNDF:
-    case BUILT_IN_LLROUNDL:
+    CASE_FLT_FN (BUILT_IN_LCEIL):
+    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_LLROUND):
       return fold_builtin_int_roundingfn (fndecl, arglist);
 
-    case BUILT_IN_LRINT:
-    case BUILT_IN_LRINTF:
-    case BUILT_IN_LRINTL:
-    case BUILT_IN_LLRINT:
-    case BUILT_IN_LLRINTF:
-    case BUILT_IN_LLRINTL:
+    CASE_FLT_FN (BUILT_IN_LRINT):
+    CASE_FLT_FN (BUILT_IN_LLRINT):
       return fold_fixed_mathfn (fndecl, arglist);
 
-    case BUILT_IN_FFS:
-    case BUILT_IN_FFSL:
-    case BUILT_IN_FFSLL:
-    case BUILT_IN_CLZ:
-    case BUILT_IN_CLZL:
-    case BUILT_IN_CLZLL:
-    case BUILT_IN_CTZ:
-    case BUILT_IN_CTZL:
-    case BUILT_IN_CTZLL:
-    case BUILT_IN_POPCOUNT:
-    case BUILT_IN_POPCOUNTL:
-    case BUILT_IN_POPCOUNTLL:
-    case BUILT_IN_PARITY:
-    case BUILT_IN_PARITYL:
-    case BUILT_IN_PARITYLL:
+    CASE_INT_FN (BUILT_IN_FFS):
+    CASE_INT_FN (BUILT_IN_CLZ):
+    CASE_INT_FN (BUILT_IN_CTZ):
+    CASE_INT_FN (BUILT_IN_POPCOUNT):
+    CASE_INT_FN (BUILT_IN_PARITY):
       return fold_builtin_bitop (fndecl, arglist);
 
     case BUILT_IN_MEMCPY:
@@ -8889,9 +8719,7 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     case BUILT_IN_MEMMOVE:
       return fold_builtin_memmove (arglist, type);
 
-    case BUILT_IN_SIGNBIT:
-    case BUILT_IN_SIGNBITF:
-    case BUILT_IN_SIGNBITL:
+    CASE_FLT_FN (BUILT_IN_SIGNBIT):
       return fold_builtin_signbit (fndecl, arglist);
 
     case BUILT_IN_ISASCII:
@@ -8903,24 +8731,25 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     case BUILT_IN_ISDIGIT:
       return fold_builtin_isdigit (arglist);
 
-    case BUILT_IN_COPYSIGN:
-    case BUILT_IN_COPYSIGNF:
-    case BUILT_IN_COPYSIGNL:
+    CASE_FLT_FN (BUILT_IN_COPYSIGN):
       return fold_builtin_copysign (fndecl, arglist, type);
 
-    case BUILT_IN_FINITE:
-    case BUILT_IN_FINITEF:
-    case BUILT_IN_FINITEL:
+    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 BUILT_IN_ISINF:
-    case BUILT_IN_ISINFF:
-    case BUILT_IN_ISINFL:
+    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 BUILT_IN_ISNAN:
-    case BUILT_IN_ISNANF:
-    case BUILT_IN_ISNANL:
+    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:
@@ -9159,8 +8988,10 @@ fold_builtin_strstr (tree arglist, tree type)
          return fold_convert (type, tem);
        }
 
+      /* The argument is const char *, and the result is char *, so we need
+        a type conversion here to avoid a warning.  */
       if (p2[0] == '\0')
-       return s1;
+       return fold_convert (type, s1);
 
       if (p2[1] != '\0')
        return 0;
@@ -9569,14 +9400,15 @@ tree
 fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
 {
   tree fn;
-  tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
+  /* If we're using an unlocked function, assume the other unlocked
+     functions exist explicitly.  */
+  tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
     : implicit_built_in_decls[BUILT_IN_FPUTC];
-  tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
+  tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
     : implicit_built_in_decls[BUILT_IN_FWRITE];
 
-  /* If the return value is used, or the replacement _DECL isn't
-     initialized, don't do the transformation.  */
-  if (!ignore || !fn_fputc || !fn_fwrite)
+  /* If the return value is used, don't do the transformation.  */
+  if (!ignore)
     return 0;
 
   /* Verify the arguments in the original call.  */
@@ -9638,6 +9470,11 @@ fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
       gcc_unreachable ();
     }
 
+  /* If the replacement _DECL isn't initialized, don't do the
+     transformation.  */
+  if (!fn)
+    return 0;
+
   /* These optimizations are only performed when the result is ignored,
      hence there's no need to cast the result to integer_type_node.  */
   return build_function_call_expr (fn, arglist);
@@ -9743,8 +9580,11 @@ fold_builtin_sprintf (tree arglist, int ignored)
   call = NULL_TREE;
   retval = NULL_TREE;
 
+  if (!init_target_chars())
+    return 0;
+
   /* If the format doesn't contain % args or %%, use strcpy.  */
-  if (strchr (fmt_str, '%') == NULL)
+  if (strchr (fmt_str, target_percent) == NULL)
     {
       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
 
@@ -9761,7 +9601,7 @@ fold_builtin_sprintf (tree arglist, int ignored)
     }
 
   /* If the format is "%s", use strcpy if the result isn't used.  */
-  else if (fmt_str && strcmp (fmt_str, "%s") == 0)
+  else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
     {
       tree fn, orig;
       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
@@ -10058,12 +9898,15 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
   if (fmt_str == NULL)
     return;
 
+  if (!init_target_chars())
+    return;
+
   /* If the format doesn't contain % args or %%, we know its size.  */
-  if (strchr (fmt_str, '%') == 0)
+  if (strchr (fmt_str, target_percent) == 0)
     len = build_int_cstu (size_type_node, strlen (fmt_str));
   /* If the format is "%s" and first ... argument is a string literal,
      we know it too.  */
-  else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, "%s") == 0)
+  else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
     {
       tree arg;
 
@@ -10518,19 +10361,22 @@ fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
 
   len = NULL_TREE;
 
+  if (!init_target_chars())
+    return 0;
+
   /* Check whether the format is a literal string constant.  */
   fmt_str = c_getstr (fmt);
   if (fmt_str != NULL)
     {
       /* If the format doesn't contain % args or %%, we know the size.  */
-      if (strchr (fmt_str, '%') == 0)
+      if (strchr (fmt_str, target_percent) == 0)
        {
          if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
            len = build_int_cstu (size_type_node, strlen (fmt_str));
        }
       /* If the format is "%s" and first ... argument is a string literal,
         we know the size too.  */
-      else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, "%s") == 0)
+      else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
        {
          tree arg;
 
@@ -10559,7 +10405,7 @@ fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
     {
       if (fmt_str == NULL)
        return 0;
-      if (strchr (fmt_str, '%') != NULL && strcmp (fmt_str, "%s"))
+      if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
        return 0;
     }
 
@@ -10640,6 +10486,9 @@ fold_builtin_snprintf_chk (tree arglist, tree maxlen,
        return 0;
     }
 
+  if (!init_target_chars())
+    return 0;
+
   /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
      or if format doesn't contain % chars or is "%s".  */
   if (! integer_zerop (flag))
@@ -10647,7 +10496,7 @@ fold_builtin_snprintf_chk (tree arglist, tree maxlen,
       fmt_str = c_getstr (fmt);
       if (fmt_str == NULL)
        return 0;
-      if (strchr (fmt_str, '%') != NULL && strcmp (fmt_str, "%s"))
+      if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
        return 0;
     }
 
@@ -10710,8 +10559,10 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
 
   if (fcode == BUILT_IN_PRINTF_UNLOCKED)
     {
-      fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
-      fn_puts = implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED];
+      /* If we're using an unlocked function, assume the other
+        unlocked functions exist explicitly.  */
+      fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
+      fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
     }
   else
     {
@@ -10719,11 +10570,14 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
       fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
     }
 
-  if (strcmp (fmt_str, "%s") == 0 || strchr (fmt_str, '%') == NULL)
+  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, "%s") == 0)
+      if (strcmp (fmt_str, target_percent_s) == 0)
        {
          if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
            return 0;
@@ -10764,7 +10618,7 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
        {
          /* If the string was "string\n", call puts("string").  */
          size_t len = strlen (str);
-         if (str[len - 1] == '\n')
+         if ((unsigned char)str[len - 1] == target_newline)
            {
              /* Create a NUL-terminated string that's one char shorter
                 than the original, stripping off the trailing '\n'.  */
@@ -10788,7 +10642,7 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
     return 0;
 
   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
-  else if (strcmp (fmt_str, "%s\n") == 0)
+  else if (strcmp (fmt_str, target_percent_s_newline) == 0)
     {
       if (! arglist
          || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
@@ -10798,7 +10652,7 @@ fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
     }
 
   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
-  else if (strcmp (fmt_str, "%c") == 0)
+  else if (strcmp (fmt_str, target_percent_c) == 0)
     {
       if (! arglist
          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -10866,8 +10720,10 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
 
   if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
     {
-      fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
-      fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
+      /* If we're using an unlocked function, assume the other
+        unlocked functions exist explicitly.  */
+      fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
+      fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
     }
   else
     {
@@ -10875,8 +10731,11 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
       fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
     }
 
+  if (!init_target_chars())
+    return 0;
+  
   /* If the format doesn't contain % args or %%, use strcpy.  */
-  if (strchr (fmt_str, '%') == NULL)
+  if (strchr (fmt_str, target_percent) == NULL)
     {
       if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
          && arglist)
@@ -10906,7 +10765,7 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
     return 0;
 
   /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
-  else if (strcmp (fmt_str, "%s") == 0)
+  else if (strcmp (fmt_str, target_percent_s) == 0)
     {
       if (! arglist
          || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
@@ -10919,7 +10778,7 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
     }
 
   /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
-  else if (strcmp (fmt_str, "%c") == 0)
+  else if (strcmp (fmt_str, target_percent_c) == 0)
     {
       if (! arglist
          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -10937,3 +10796,37 @@ fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
   call = build_function_call_expr (fn, arglist);
   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
 }
+
+/* Initialize format string characters in the target charset.  */
+
+static bool
+init_target_chars (void)
+{
+  static bool init;
+  if (!init)
+    {
+      target_newline = lang_hooks.to_target_charset ('\n');
+      target_percent = lang_hooks.to_target_charset ('%');
+      target_c = lang_hooks.to_target_charset ('c');
+      target_s = lang_hooks.to_target_charset ('s');
+      if (target_newline == 0 || target_percent == 0 || target_c == 0
+         || target_s == 0)
+       return false;
+
+      target_percent_c[0] = target_percent;
+      target_percent_c[1] = target_c;
+      target_percent_c[2] = '\0';
+
+      target_percent_s[0] = target_percent;
+      target_percent_s[1] = target_s;
+      target_percent_s[2] = '\0';
+
+      target_percent_s_newline[0] = target_percent;
+      target_percent_s_newline[1] = target_s;
+      target_percent_s_newline[2] = target_newline;
+      target_percent_s_newline[3] = '\0';
+      
+      init = true;
+    }
+  return true;
+}