Message ID | 20101118110655.GV29412@tyan-ft48-01.lab.bos.redhat.com |
---|---|
State | New |
Headers | show |
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 >
--- 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"); +}