This moves fold_builtin_strncat and fold_builtin_printf.

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

Richard.

2014-12-03  Richard Biener  <rguent...@suse.de>

        * builtins.c (target_newline): Export.
        (target_percent_s_newline): Likewise.
        (fold_builtin_1): Do not fold printf functions here.
        (fold_builtin_2): Likewise.
        (fold_builtin_3): Likewise, do not fold strncat.
        (fold_builtin_strncat): Move to gimple-fold.c.
        (fold_builtin_printf): Likewise.
        * builtins.h (target_newline): Declare.
        (target_percent_s_newline): Likewise.
        * gimple-fold.c (gimple_fold_builtin_strncat): Move from
        builtins.c and gimplify.
        (gimple_fold_builtin_printf): Likewise.
        (gimple_fold_builtin): Fold strncat, printf, printf_unlocked,
        vprintf, printf_chk and vprintf_chk here.

Index: trunk/gcc/builtins.c
===================================================================
*** trunk.orig/gcc/builtins.c   2014-12-03 14:07:41.745831293 +0100
--- trunk/gcc/builtins.c        2014-12-03 14:26:47.102791637 +0100
*************** static tree fold_builtin_varargs (locati
*** 200,206 ****
  static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
  static tree fold_builtin_strstr (location_t, tree, tree, tree);
  static tree fold_builtin_strrchr (location_t, tree, tree, tree);
- static tree fold_builtin_strncat (location_t, tree, tree, tree);
  static tree fold_builtin_strspn (location_t, tree, tree);
  static tree fold_builtin_strcspn (location_t, tree, tree);
  
--- 200,205 ----
*************** static void maybe_emit_chk_warning (tree
*** 211,225 ****
  static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
  static void maybe_emit_free_warning (tree);
  static tree fold_builtin_object_size (tree, tree);
- static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum 
built_in_function);
  
! static unsigned HOST_WIDE_INT target_newline;
  unsigned HOST_WIDE_INT target_percent;
  static unsigned HOST_WIDE_INT target_c;
  static unsigned HOST_WIDE_INT target_s;
  char target_percent_c[3];
  char target_percent_s[3];
! static char target_percent_s_newline[4];
  static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, 
mp_rnd_t),
                          const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, 
bool);
  static tree do_mpfr_arg2 (tree, tree, tree,
--- 210,223 ----
  static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
  static void maybe_emit_free_warning (tree);
  static tree fold_builtin_object_size (tree, tree);
  
! unsigned HOST_WIDE_INT target_newline;
  unsigned HOST_WIDE_INT target_percent;
  static unsigned HOST_WIDE_INT target_c;
  static unsigned HOST_WIDE_INT target_s;
  char target_percent_c[3];
  char target_percent_s[3];
! char target_percent_s_newline[4];
  static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, 
mp_rnd_t),
                          const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, 
bool);
  static tree do_mpfr_arg2 (tree, tree, tree,
*************** fold_builtin_0 (location_t loc, tree fnd
*** 9892,9898 ****
     function returns NULL_TREE if no simplification was possible.  */
  
  static tree
! fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
--- 9890,9896 ----
     function returns NULL_TREE if no simplification was possible.  */
  
  static tree
! fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
*************** fold_builtin_1 (location_t loc, tree fnd
*** 10289,10299 ****
      case BUILT_IN_ISNAND128:
        return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
  
-     case BUILT_IN_PRINTF:
-     case BUILT_IN_PRINTF_UNLOCKED:
-     case BUILT_IN_VPRINTF:
-       return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, 
fcode);
- 
      case BUILT_IN_FREE:
        if (integer_zerop (arg0))
        return build_empty_stmt (loc);
--- 10287,10292 ----
*************** fold_builtin_2 (location_t loc, tree fnd
*** 10463,10483 ****
      case BUILT_IN_OBJECT_SIZE:
        return fold_builtin_object_size (arg0, arg1);
  
-     case BUILT_IN_PRINTF:
-     case BUILT_IN_PRINTF_UNLOCKED:
-     case BUILT_IN_VPRINTF:
-       return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
- 
-     case BUILT_IN_PRINTF_CHK:
-     case BUILT_IN_VPRINTF_CHK:
-       if (!validate_arg (arg0, INTEGER_TYPE)
-         || TREE_SIDE_EFFECTS (arg0))
-       return NULL_TREE;
-       else
-       return fold_builtin_printf (loc, fndecl,
-                                   arg1, NULL_TREE, ignore, fcode);
-     break;
- 
      case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
        return fold_builtin_atomic_always_lock_free (arg0, arg1);
  
--- 10456,10461 ----
*************** fold_builtin_2 (location_t loc, tree fnd
*** 10496,10502 ****
  
  static tree
  fold_builtin_3 (location_t loc, tree fndecl,
!               tree arg0, tree arg1, tree arg2, bool ignore)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
--- 10474,10480 ----
  
  static tree
  fold_builtin_3 (location_t loc, tree fndecl,
!               tree arg0, tree arg1, tree arg2, bool)
  {
    tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
*************** fold_builtin_3 (location_t loc, tree fnd
*** 10517,10525 ****
        return do_mpfr_remquo (arg0, arg1, arg2);
      break;
  
-     case BUILT_IN_STRNCAT:
-       return fold_builtin_strncat (loc, arg0, arg1, arg2);
- 
      case BUILT_IN_STRNCMP:
        return fold_builtin_strncmp (loc, arg0, arg1, arg2);
  
--- 10495,10500 ----
*************** fold_builtin_3 (location_t loc, tree fnd
*** 10530,10544 ****
      case BUILT_IN_MEMCMP:
        return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
  
-     case BUILT_IN_PRINTF_CHK:
-     case BUILT_IN_VPRINTF_CHK:
-       if (!validate_arg (arg0, INTEGER_TYPE)
-         || TREE_SIDE_EFFECTS (arg0))
-       return NULL_TREE;
-       else
-       return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
-     break;
- 
      case BUILT_IN_EXPECT:
        return fold_builtin_expect (loc, arg0, arg1, arg2);
  
--- 10505,10510 ----
*************** fold_builtin_strpbrk (location_t loc, tr
*** 11118,11175 ****
      }
  }
  
- /* Simplify a call to the strncat builtin.  DST, SRC, and LEN are the
-    arguments to the call.
- 
-    Return NULL_TREE if no simplification was possible, otherwise return the
-    simplified form of the call as a tree.
- 
-    The simplified form may be a constant or other expression which
-    computes the same value, but in a more efficient manner (including
-    calls to other builtin functions).
- 
-    The call may contain arguments which need to be evaluated, but
-    which are not useful to determine the result of the call.  In
-    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
-    COMPOUND_EXPR will be an argument which must be evaluated.
-    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
-    COMPOUND_EXPR in the chain will contain the tree for the simplified
-    form of the builtin function call.  */
- 
- static tree
- fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
- {
-   if (!validate_arg (dst, POINTER_TYPE)
-       || !validate_arg (src, POINTER_TYPE)
-       || !validate_arg (len, INTEGER_TYPE))
-     return NULL_TREE;
-   else
-     {
-       const char *p = c_getstr (src);
- 
-       /* 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_loc (loc, TREE_TYPE (dst), dst, src, len);
- 
-       /* If the requested len is greater than or equal to the string
-        length, call strcat.  */
-       if (TREE_CODE (len) == INTEGER_CST && p
-         && compare_tree_int (len, strlen (p)) >= 0)
-       {
-         tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
- 
-         /* If the replacement _DECL isn't initialized, don't do the
-            transformation.  */
-         if (!fn)
-           return NULL_TREE;
- 
-         return build_call_expr_loc (loc, fn, 2, dst, src);
-       }
-       return NULL_TREE;
-     }
- }
- 
  /* Simplify a call to the strspn builtin.  S1 and S2 are the arguments
     to the call.
  
--- 11084,11089 ----
*************** fold_builtin_varargs (location_t loc, tr
*** 11771,11925 ****
    return NULL_TREE;
  }
  
- /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
-    FMT and ARG are the arguments to the call; we don't fold cases with
-    more than 2 arguments, and ARG may be null if this is a 1-argument case.
- 
-    Return NULL_TREE if no simplification was possible, otherwise return the
-    simplified form of the call as a tree.  FCODE is the BUILT_IN_*
-    code of the function to be simplified.  */
- 
- static tree
- fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
-                    tree arg, bool ignore,
-                    enum built_in_function fcode)
- {
-   tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
-   const char *fmt_str = NULL;
- 
-   /* If the return value is used, don't do the transformation.  */
-   if (! ignore)
-     return NULL_TREE;
- 
-   /* Verify the required arguments in the original call.  */
-   if (!validate_arg (fmt, POINTER_TYPE))
-     return NULL_TREE;
- 
-   /* Check whether the format is a literal string constant.  */
-   fmt_str = c_getstr (fmt);
-   if (fmt_str == NULL)
-     return NULL_TREE;
- 
-   if (fcode == BUILT_IN_PRINTF_UNLOCKED)
-     {
-       /* If we're using an unlocked function, assume the other
-        unlocked functions exist explicitly.  */
-       fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
-       fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
-     }
-   else
-     {
-       fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
-       fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
-     }
- 
-   if (!init_target_chars ())
-     return NULL_TREE;
- 
-   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)
-       {
-         if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
-           return NULL_TREE;
- 
-         if (!arg || !validate_arg (arg, POINTER_TYPE))
-           return NULL_TREE;
- 
-         str = c_getstr (arg);
-         if (str == NULL)
-           return NULL_TREE;
-       }
-       else
-       {
-         /* The format specifier doesn't contain any '%' characters.  */
-         if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
-             && arg)
-           return NULL_TREE;
-         str = fmt_str;
-       }
- 
-       /* If the string was "", printf does nothing.  */
-       if (str[0] == '\0')
-       return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
- 
-       /* If the string has length of 1, call putchar.  */
-       if (str[1] == '\0')
-       {
-         /* Given printf("c"), (where c is any one character,)
-            convert "c"[0] to an int and pass that to the replacement
-            function.  */
-         newarg = build_int_cst (integer_type_node, str[0]);
-         if (fn_putchar)
-           call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
-       }
-       else
-       {
-         /* If the string was "string\n", call puts("string").  */
-         size_t len = strlen (str);
-         if ((unsigned char)str[len - 1] == target_newline
-             && (size_t) (int) len == len
-             && (int) len > 0)
-           {
-             char *newstr;
-             tree offset_node, string_cst;
- 
-             /* Create a NUL-terminated string that's one char shorter
-                than the original, stripping off the trailing '\n'.  */
-             newarg = build_string_literal (len, str);
-             string_cst = string_constant (newarg, &offset_node);
-             gcc_checking_assert (string_cst
-                                  && (TREE_STRING_LENGTH (string_cst)
-                                      == (int) len)
-                                  && integer_zerop (offset_node)
-                                  && (unsigned char)
-                                     TREE_STRING_POINTER (string_cst)[len - 1]
-                                     == target_newline);
-             /* build_string_literal creates a new STRING_CST,
-                modify it in place to avoid double copying.  */
-             newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
-             newstr[len - 1] = '\0';
-             if (fn_puts)
-               call = build_call_expr_loc (loc, fn_puts, 1, newarg);
-           }
-         else
-           /* We'd like to arrange to call fputs(string,stdout) here,
-              but we need stdout and don't have a way to get it yet.  */
-           return NULL_TREE;
-       }
-     }
- 
-   /* The other optimizations can be done only on the non-va_list variants.  */
-   else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
-     return NULL_TREE;
- 
-   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
-   else if (strcmp (fmt_str, target_percent_s_newline) == 0)
-     {
-       if (!arg || !validate_arg (arg, POINTER_TYPE))
-       return NULL_TREE;
-       if (fn_puts)
-       call = build_call_expr_loc (loc, fn_puts, 1, arg);
-     }
- 
-   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
-   else if (strcmp (fmt_str, target_percent_c) == 0)
-     {
-       if (!arg || !validate_arg (arg, INTEGER_TYPE))
-       return NULL_TREE;
-       if (fn_putchar)
-       call = build_call_expr_loc (loc, fn_putchar, 1, arg);
-     }
- 
-   if (!call)
-     return NULL_TREE;
- 
-   return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
- }
- 
  /* Initialize format string characters in the target charset.  */
  
  bool
--- 11685,11690 ----
Index: trunk/gcc/builtins.h
===================================================================
*** trunk.orig/gcc/builtins.h   2014-12-03 14:07:41.745831293 +0100
--- trunk/gcc/builtins.h        2014-12-03 14:25:40.975793927 +0100
*************** extern bool is_inexpensive_builtin (tree
*** 89,96 ****
--- 89,98 ----
  extern bool readonly_data_expr (tree exp);
  extern const char *c_getstr (tree);
  extern bool init_target_chars (void);
+ extern unsigned HOST_WIDE_INT target_newline;
  extern unsigned HOST_WIDE_INT target_percent;
  extern char target_percent_s[3];
  extern char target_percent_c[3];
+ extern char target_percent_s_newline[4];
  
  #endif
Index: trunk/gcc/gimple-fold.c
===================================================================
*** trunk.orig/gcc/gimple-fold.c        2014-12-03 14:07:41.746831293 +0100
--- trunk/gcc/gimple-fold.c     2014-12-03 14:29:56.420785083 +0100
*************** gimple_fold_builtin_strcat_chk (gimple_s
*** 1628,1633 ****
--- 1628,1673 ----
    return true;
  }
  
+ /* Simplify a call to the strncat builtin.  */
+ 
+ static bool
+ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
+ {
+   gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+   tree dst = gimple_call_arg (stmt, 0);
+   tree src = gimple_call_arg (stmt, 1);
+   tree len = gimple_call_arg (stmt, 2);
+ 
+   const char *p = c_getstr (src);
+ 
+   /* 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'))
+     {
+       replace_call_with_value (gsi, dst);
+       return true;
+     }
+ 
+   /* If the requested len is greater than or equal to the string
+      length, call strcat.  */
+   if (TREE_CODE (len) == INTEGER_CST && p
+       && compare_tree_int (len, strlen (p)) >= 0)
+     {
+       tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
+ 
+       /* If the replacement _DECL isn't initialized, don't do the
+        transformation.  */
+       if (!fn)
+       return false;
+ 
+       gcall *repl = gimple_build_call (fn, 2, dst, src);
+       replace_call_with_call_and_fold (gsi, repl);
+       return true;
+     }
+ 
+   return false;
+ }
+ 
  /* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
     LEN, and SIZE.  */
  
*************** gimple_fold_builtin_fprintf (gimple_stmt
*** 2554,2559 ****
--- 2594,2761 ----
    return false;
  }
  
+ /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
+    FMT and ARG are the arguments to the call; we don't fold cases with
+    more than 2 arguments, and ARG may be null if this is a 1-argument case.
+ 
+    Return NULL_TREE if no simplification was possible, otherwise return the
+    simplified form of the call as a tree.  FCODE is the BUILT_IN_*
+    code of the function to be simplified.  */
+ 
+ static bool
+ gimple_fold_builtin_printf (gimple_stmt_iterator *gsi, tree fmt,
+                           tree arg, enum built_in_function fcode)
+ {
+   gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+   tree fn_putchar, fn_puts, newarg;
+   const char *fmt_str = NULL;
+ 
+   /* If the return value is used, don't do the transformation.  */
+   if (gimple_call_lhs (stmt) != NULL_TREE)
+     return false;
+ 
+   /* Check whether the format is a literal string constant.  */
+   fmt_str = c_getstr (fmt);
+   if (fmt_str == NULL)
+     return false;
+ 
+   if (fcode == BUILT_IN_PRINTF_UNLOCKED)
+     {
+       /* If we're using an unlocked function, assume the other
+        unlocked functions exist explicitly.  */
+       fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
+       fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
+     }
+   else
+     {
+       fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
+       fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
+     }
+ 
+   if (!init_target_chars ())
+     return false;
+ 
+   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)
+       {
+         if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
+           return false;
+ 
+         if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg)))
+           return false;
+ 
+         str = c_getstr (arg);
+         if (str == NULL)
+           return false;
+       }
+       else
+       {
+         /* The format specifier doesn't contain any '%' characters.  */
+         if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
+             && arg)
+           return false;
+         str = fmt_str;
+       }
+ 
+       /* If the string was "", printf does nothing.  */
+       if (str[0] == '\0')
+       {
+         replace_call_with_value (gsi, NULL_TREE);
+         return true;
+       }
+ 
+       /* If the string has length of 1, call putchar.  */
+       if (str[1] == '\0')
+       {
+         /* Given printf("c"), (where c is any one character,)
+            convert "c"[0] to an int and pass that to the replacement
+            function.  */
+         newarg = build_int_cst (integer_type_node, str[0]);
+         if (fn_putchar)
+           {
+             gcall *repl = gimple_build_call (fn_putchar, 1, newarg);
+             replace_call_with_call_and_fold (gsi, repl);
+             return true;
+           }
+       }
+       else
+       {
+         /* If the string was "string\n", call puts("string").  */
+         size_t len = strlen (str);
+         if ((unsigned char)str[len - 1] == target_newline
+             && (size_t) (int) len == len
+             && (int) len > 0)
+           {
+             char *newstr;
+             tree offset_node, string_cst;
+ 
+             /* Create a NUL-terminated string that's one char shorter
+                than the original, stripping off the trailing '\n'.  */
+             newarg = build_string_literal (len, str);
+             string_cst = string_constant (newarg, &offset_node);
+             gcc_checking_assert (string_cst
+                                  && (TREE_STRING_LENGTH (string_cst)
+                                      == (int) len)
+                                  && integer_zerop (offset_node)
+                                  && (unsigned char)
+                                     TREE_STRING_POINTER (string_cst)[len - 1]
+                                     == target_newline);
+             /* build_string_literal creates a new STRING_CST,
+                modify it in place to avoid double copying.  */
+             newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
+             newstr[len - 1] = '\0';
+             if (fn_puts)
+               {
+                 gcall *repl = gimple_build_call (fn_puts, 1, newarg);
+                 replace_call_with_call_and_fold (gsi, repl);
+                 return true;
+               }
+           }
+         else
+           /* We'd like to arrange to call fputs(string,stdout) here,
+              but we need stdout and don't have a way to get it yet.  */
+           return false;
+       }
+     }
+ 
+   /* The other optimizations can be done only on the non-va_list variants.  */
+   else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
+     return false;
+ 
+   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
+   else if (strcmp (fmt_str, target_percent_s_newline) == 0)
+     {
+       if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg)))
+       return false;
+       if (fn_puts)
+       {
+         gcall *repl = gimple_build_call (fn_puts, 1, arg);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+     }
+ 
+   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
+   else if (strcmp (fmt_str, target_percent_c) == 0)
+     {
+       if (!arg || ! useless_type_conversion_p (integer_type_node,
+                                              TREE_TYPE (arg)))
+       return false;
+       if (fn_putchar)
+       {
+         gcall *repl = gimple_build_call (fn_putchar, 1, arg);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+     }
+ 
+   return false;
+ }
+ 
  
  
  /* Fold a call to __builtin_strlen with known length LEN.  */
*************** gimple_fold_builtin (gimple_stmt_iterato
*** 2629,2634 ****
--- 2831,2838 ----
      case BUILT_IN_STRCAT:
        return gimple_fold_builtin_strcat (gsi, gimple_call_arg (stmt, 0),
                                         gimple_call_arg (stmt, 1));
+     case BUILT_IN_STRNCAT:
+       return gimple_fold_builtin_strncat (gsi);
      case BUILT_IN_FPUTS:
        return gimple_fold_builtin_fputs (gsi, gimple_call_arg (stmt, 0),
                                        gimple_call_arg (stmt, 1), false);
*************** gimple_fold_builtin (gimple_stmt_iterato
*** 2690,2695 ****
--- 2894,2915 ----
                                            : NULL_TREE,
                                            fcode);
        break;
+     case BUILT_IN_PRINTF:
+     case BUILT_IN_PRINTF_UNLOCKED:
+     case BUILT_IN_VPRINTF:
+       if (n == 1 || n == 2)
+       return gimple_fold_builtin_printf (gsi, gimple_call_arg (stmt, 0),
+                                          n == 2
+                                          ? gimple_call_arg (stmt, 1)
+                                          : NULL_TREE, fcode);
+       break;
+     case BUILT_IN_PRINTF_CHK:
+     case BUILT_IN_VPRINTF_CHK:
+       if (n == 2 || n == 3)
+       return gimple_fold_builtin_printf (gsi, gimple_call_arg (stmt, 1),
+                                          n == 3
+                                          ? gimple_call_arg (stmt, 2)
+                                          : NULL_TREE, fcode);
      default:;
      }
  

Reply via email to