diff mbox

Fix ICE on printf optimization with very large format string (PR middle-end/46534)

Message ID 20101118110655.GV29412@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 18, 2010, 11:06 a.m. UTC
Hi!

For the printf ("...\n") -> puts ("...") optimization we use alloca
to copy the string and change it before passing it to build_string_literal.
This doesn't work very well if the string is so long that we hit
RLIMIT_STACK.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2010-11-18  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/46534
	* builtins.c (fold_builtin_printf): Don't use XALLOCAVEC for
	large strings.

	* gcc.c-torture/compile/pr46534.c: New test.


	Jakub

Comments

Richard Biener Nov. 18, 2010, 12:09 p.m. UTC | #1
On Thu, Nov 18, 2010 at 12:06 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> For the printf ("...\n") -> puts ("...") optimization we use alloca
> to copy the string and change it before passing it to build_string_literal.
> This doesn't work very well if the string is so long that we hit
> RLIMIT_STACK.
>
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?

As stated in the PR we can avoid the copying completely if by
adjusting tree.c:build_string to do this modification itself.  No need
to copy things twice.

Richard.

> 2010-11-18  Jakub Jelinek  <jakub@redhat.com>
>
>        PR middle-end/46534
>        * builtins.c (fold_builtin_printf): Don't use XALLOCAVEC for
>        large strings.
>
>        * gcc.c-torture/compile/pr46534.c: New test.
>
> --- gcc/builtins.c.jj   2010-11-16 21:47:24.000000000 +0100
> +++ gcc/builtins.c      2010-11-18 09:44:19.118405504 +0100
> @@ -12891,12 +12891,19 @@ fold_builtin_printf (location_t loc, tre
>          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'.  */
> -             char *newstr = XALLOCAVEC (char, len);
> +                than the original, stripping off the trailing '\n'.
> +                Don't use XALLOCAVEC if the string is too long.  */
> +             char *newstr;
> +             if (len > 16384)
> +               newstr = XNEWVEC (char, len);
> +             else
> +               newstr = XALLOCAVEC (char, len);
>              memcpy (newstr, str, len - 1);
>              newstr[len - 1] = 0;
>
>              newarg = build_string_literal (len, newstr);
> +             if (len > 16384)
> +               XDELETEVEC (newstr);
>              if (fn_puts)
>                call = build_call_expr_loc (loc, fn_puts, 1, newarg);
>            }
> --- gcc/testsuite/gcc.c-torture/compile/pr46534.c.jj    2010-11-18 09:45:01.896404633 +0100
> +++ gcc/testsuite/gcc.c-torture/compile/pr46534.c       2010-11-18 09:45:11.943542267 +0100
> @@ -0,0 +1,17 @@
> +/* PR middle-end/46534 */
> +
> +extern int printf (const char *, ...);
> +
> +#define S1 "                    "
> +#define S2 S1 S1 S1 S1 S1 S1 S1 S1 S1 S1
> +#define S3 S2 S2 S2 S2 S2 S2 S2 S2 S2 S2
> +#define S4 S3 S3 S3 S3 S3 S3 S3 S3 S3 S3
> +#define S5 S4 S4 S4 S4 S4 S4 S4 S4 S4 S4
> +#define S6 S5 S5 S5 S5 S5 S5 S5 S5 S5 S5
> +#define S7 S6 S6 S6 S6 S6 S6 S6 S6 S6 S6
> +
> +void
> +foo (void)
> +{
> +  printf (S7 "\n");
> +}
>
>        Jakub
>
diff mbox

Patch

--- gcc/builtins.c.jj	2010-11-16 21:47:24.000000000 +0100
+++ gcc/builtins.c	2010-11-18 09:44:19.118405504 +0100
@@ -12891,12 +12891,19 @@  fold_builtin_printf (location_t loc, tre
 	  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'.  */
-	      char *newstr = XALLOCAVEC (char, len);
+		 than the original, stripping off the trailing '\n'.
+		 Don't use XALLOCAVEC if the string is too long.  */
+	      char *newstr;
+	      if (len > 16384)
+		newstr = XNEWVEC (char, len);
+	      else
+		newstr = XALLOCAVEC (char, len);
 	      memcpy (newstr, str, len - 1);
 	      newstr[len - 1] = 0;
 
 	      newarg = build_string_literal (len, newstr);
+	      if (len > 16384)
+		XDELETEVEC (newstr);
 	      if (fn_puts)
 		call = build_call_expr_loc (loc, fn_puts, 1, newarg);
 	    }
--- gcc/testsuite/gcc.c-torture/compile/pr46534.c.jj	2010-11-18 09:45:01.896404633 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr46534.c	2010-11-18 09:45:11.943542267 +0100
@@ -0,0 +1,17 @@ 
+/* PR middle-end/46534 */
+
+extern int printf (const char *, ...);
+
+#define S1 "                    "
+#define S2 S1 S1 S1 S1 S1 S1 S1 S1 S1 S1
+#define S3 S2 S2 S2 S2 S2 S2 S2 S2 S2 S2
+#define S4 S3 S3 S3 S3 S3 S3 S3 S3 S3 S3
+#define S5 S4 S4 S4 S4 S4 S4 S4 S4 S4 S4
+#define S6 S5 S5 S5 S5 S5 S5 S5 S5 S5 S5
+#define S7 S6 S6 S6 S6 S6 S6 S6 S6 S6 S6
+
+void
+foo (void)
+{
+  printf (S7 "\n");
+}