public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* Re: optimization/5477: gcc 3.0.x reserves a large stack frame, but uses only some parts of it
@ 2003-03-17 10:36 Klaus Espenlaub
  0 siblings, 0 replies; 4+ messages in thread
From: Klaus Espenlaub @ 2003-03-17 10:36 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR optimization/5477; it has been noted by GNATS.

From: Klaus Espenlaub <espenlaub@informatik.uni-ulm.de>
To: bangerth@dealii.org,  gcc-bugs@gcc.gnu.org,  gcc-prs@gcc.gnu.org, 
 nobody@gcc.gnu.org,  gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: optimization/5477: gcc 3.0.x reserves a large stack frame, but
 uses only some parts of it
Date: Mon, 17 Mar 2003 11:33:57 +0100

 bangerth@dealii.org wrote:
 > Synopsis: gcc 3.0.x reserves a large stack frame, but uses only some parts of it
 > 
 > State-Changed-From-To: open->feedback
 > State-Changed-By: bangerth
 > State-Changed-When: Sat Mar 15 04:38:32 2003
 > State-Changed-Why:
 >     Klaus, for unknown reasons the attachment I find in the
 >     report doesn't have a main() function -- thus no checking
 >     possible. Do you still have the program so that you can
 >     send it to me? I'll attach it to the report then.
 
 The code is taken from a libc subset, therefore there is no main().
 If you insist on having a piece of code that can be compiled to an executable
 program, just append the following few lines to the code:
 
 -------------------------- snip
 int __console_putchar(int c)
 {
          return putchar(c);
 }
 
 int main(void)
 {
 	do_printf(NULL, 30, "Hello, world!\n", NULL);
 	return 0;
 }
 -------------------------- snip
 
 It doesn't make much sense in this context to have a fully compilable piece of
 code, since the problem is not that the resulting program fails to compile or
 fails to run, but that it uses one order of magniture more stack space than it
 would need to.  So it's no good candidate for automated regression checking,
 since neither the compiler fails nor the compiled program.  There's not much
 more possible than manually follow the How-To-Repeat section of the bug report.
 
 Another comment on the base problem: the compiler bug seems to be fixed in
 gcc-3.2.  There might still be room for improvement, but the current stack
 consumption is quite acceptable: gcc-3.0 reserved 380 bytes of stack space,
 while gcc-3.2 reserves only 28.
 
 >     Regarding the problem itself: yes, known problem. We
 >     have several such reports in the database :-(
 
 The solution for me will be to upgrade to gcc-3.2 everywhere in the very near
 future.
 
 Regards
 -- 
 Klaus Espenlaub                      Email:  espenlaub@informatik.uni-ulm.de
 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: optimization/5477: gcc 3.0.x reserves a large stack frame, but uses only some parts of it
@ 2003-03-17 23:56 Wolfgang Bangerth
  0 siblings, 0 replies; 4+ messages in thread
From: Wolfgang Bangerth @ 2003-03-17 23:56 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR optimization/5477; it has been noted by GNATS.

From: Wolfgang Bangerth <bangerth@ticam.utexas.edu>
To: Klaus Espenlaub <espenlaub@informatik.uni-ulm.de>
Cc: gcc-bugs@gcc.gnu.org, <gcc-gnats@gcc.gnu.org>
Subject: Re: optimization/5477: gcc 3.0.x reserves a large stack frame, but
 uses only some parts of it
Date: Mon, 17 Mar 2003 17:48:32 -0600 (CST)

 > > State-Changed-From-To: open->feedback
 > > State-Changed-Why:
 > >     Klaus, for unknown reasons the attachment I find in the
 > >     report doesn't have a main() function -- thus no checking
 > >     possible. Do you still have the program so that you can
 > >     send it to me? I'll attach it to the report then.
 > [...]
 > It doesn't make much sense in this context to have a fully compilable piece of
 > code, since the problem is not that the resulting program fails to compile or
 > fails to run, but that it uses one order of magniture more stack space than it
 > would need to. 
 
 My apologies -- late night staring at PRs doesn't improve my ability to 
 think. I think it just didn't get into my head to look at assembly output.
 
 > Another comment on the base problem: the compiler bug seems to be fixed in
 > gcc-3.2.  There might still be room for improvement, but the current stack
 > consumption is quite acceptable: gcc-3.0 reserved 380 bytes of stack space,
 > while gcc-3.2 reserves only 28.
 
 For me, its either 60 bytes or 44 bytes (with -DPUTCHAR_MACRO) for 3.2.2,
 present 3.3 and mainline. Not all of these stack slots seems to be used. 
 What do you suggest we do with the report?
 
 W.
 
 -------------------------------------------------------------------------
 Wolfgang Bangerth             email:            bangerth@ticam.utexas.edu
                               www: http://www.ticam.utexas.edu/~bangerth/
 
 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: optimization/5477: gcc 3.0.x reserves a large stack frame, but uses only some parts of it
@ 2003-03-15  4:38 bangerth
  0 siblings, 0 replies; 4+ messages in thread
From: bangerth @ 2003-03-15  4:38 UTC (permalink / raw)
  To: espenlaub, gcc-bugs, gcc-prs, nobody

Synopsis: gcc 3.0.x reserves a large stack frame, but uses only some parts of it

State-Changed-From-To: open->feedback
State-Changed-By: bangerth
State-Changed-When: Sat Mar 15 04:38:32 2003
State-Changed-Why:
    Klaus, for unknown reasons the attachment I find in the
    report doesn't have a main() function -- thus no checking
    possible. Do you still have the program so that you can
    send it to me? I'll attach it to the report then.
    
    Regarding the problem itself: yes, known problem. We
    have several such reports in the database :-(
    
    W.

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=5477


^ permalink raw reply	[flat|nested] 4+ messages in thread

* optimization/5477: gcc 3.0.x reserves a large stack frame, but uses only some parts of it
@ 2002-01-24  1:06 espenlaub
  0 siblings, 0 replies; 4+ messages in thread
From: espenlaub @ 2002-01-24  1:06 UTC (permalink / raw)
  To: gcc-gnats


>Number:         5477
>Category:       optimization
>Synopsis:       gcc 3.0.x reserves a large stack frame, but uses only some parts of it
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          pessimizes-code
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 24 01:06:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Klaus Espenlaub
>Release:        gcc-3.0.3
>Organization:
>Environment:
System: Linux croc 2.4.7-4GB #1 Thu Oct 25 17:53:12 GMT 2001 i686 unknown
Architecture: i686
>Description:
All recent gcc C-compiler versions (starting from 3.0)
create code that has the distinctive tendency to allocate
stack frames that are much larger than required for the
respective function.  The situation is worsened by heavy
use of small functions declared __inline__.  In my case -
embedded environment with very tight stack - this makes
recent gcc versions unusable.

The attached sample compiles to a single function, which
(on the i386 architecture) reserves 380 bytes for local
variables.  The same code compiled with gcc 2.95.3 reserves
just 108 bytes.  If the inline function printf_putchar is
replaced by an equivalent preprocessor macro, then the
stack allocation is reduced drastically to 124 bytes.
Interestingly for gcc 2.95 it doesn't make a substantial
difference whether inline functions or preprocessor macros
are used, but for gcc 3.0 it does.

As a side note: the same code compiled by g++ creates code
that uses a reasonable amount of stack, regardless of the
compiler version (2.95 or 3.0.x).
>How-To-Repeat:
(assuming that the attached file - which BTW uses #include,
but only stuff that comes with gcc - is saved to
printf-stackwaste.c)

gcc -O2 -S printf-stackwaste.c
for the version using inlining, and
gcc -O2 -S -DPUTCHAR_MACRO printf-stackwaste.c
for the version using a preprocessor macro.

The interesting number is the value that is subtracted
from %esp at the end of the epilogue for do_printf.
>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="printf-stackwaste.c"
Content-Disposition: inline; filename="printf-stackwaste.c"

#include <limits.h>
#include <stdarg.h>


/* Some gcc versions don't define LLONG_MAX, because it wasn't defined in the
 * earlier C standards.  */
#ifndef LLONG_MAX
#define LLONG_MAX 9223372036854775807LL
#endif /* LLONG_MAX */

#define NULL ((void *)0)


typedef unsigned int size_t;


#define ZEROPAD	1		/* pad with zero */
#define SIGN	2		/* unsigned/signed long */
#define PLUS	4		/* show plus */
#define SPACE	8		/* space if plus */
#define LEFT	16		/* left justified */
#define SPECIAL	32		/* 0x */
#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */


#ifdef PUTCHAR_MACRO
#define printf_putchar(buf, c) \
	if (*(buf) != NULL) { \
		**(buf) = c; \
		(*(buf))++; \
	} else { \
		__console_putchar(c); \
	}
#else
static __inline__ void printf_putchar(char **buf, unsigned char c)
{
	if (*buf != NULL) {
		**buf = c;
		(*buf)++;
	} else {
		__console_putchar(c);
	}
}
#endif

static __inline__ void number(char **str, unsigned long long num,
                              unsigned base, int size, unsigned precision,
                              int type, size_t *maxlen)
{
	char sign, tmp[22];
	static const char digits[16] = "0123456789abcdef";
	unsigned i;

	if (type & LEFT)
		type &= ~ZEROPAD;
	if (base < 8 || base > 16)
		return;
	sign = 0;
	if (type & SIGN) {
		if (num > LLONG_MAX) {
			sign = '-';
			num = -num;
			size--;
		} else if (type & PLUS) {
			sign = '+';
			size--;
		} else if (type & SPACE) {
			sign = ' ';
			size--;
		}
	}
	if (type & SPECIAL) {
		if (base == 16)
			size -= 2;
		else if (base == 8)
			size--;
	}
	i = 0;
	if (num == 0)
		tmp[i++] = '0';
	else while (num != 0) {
		tmp[i] = digits[num % base];
		num /= base;
		if ((type & LARGE) && (tmp[i] > '9')) tmp[i] &= 0xdf;
		i++;
	}
	if ((i > precision) || (precision == UINT_MAX))
		precision = i;
	size -= precision;
	if (!(type&(ZEROPAD+LEFT)))
		while((size-->0) && (*maxlen > 0)) {
			printf_putchar(str, ' ');
			(*maxlen)--;
		}
	if (sign && (*maxlen > 0)) {
		printf_putchar(str, sign);
		(*maxlen)--;
	}
	if (type & SPECIAL) {
		if ((base==8) && (*maxlen > 0)) {
			printf_putchar(str, '0');
			(*maxlen)--;
		} else if (base==16) {
			if (*maxlen > 0) {
				printf_putchar(str, '0');
				(*maxlen)--;
			}
			if (*maxlen > 0) {
				printf_putchar(str, (type & LARGE) ? 'X' : 'x');
				(*maxlen)--;
			}
		}
	}
	if (!(type & LEFT))
		while ((size-- > 0) && (*maxlen > 0)) {
			printf_putchar(str, (type & ZEROPAD) ? '0' : ' ');
			(*maxlen)--;
		}
	while ((i < precision--) && (*maxlen > 0)) {
		printf_putchar(str, '0');
		(*maxlen)--;
	}
	while ((i-- > 0) && (*maxlen > 0)) {
		printf_putchar(str, tmp[i]);
		(*maxlen)--;
	}
	while ((size-- > 0) && (*maxlen > 0)) {
		printf_putchar(str, ' ');
		(*maxlen)--;
	}
}

static __inline__ unsigned skip_atoi(const char **s)
{
	unsigned i = 0;

	while ((**s >= '0') && (**s <= '9'))
		i = i*10 + *((*s)++) - '0';
	return i;
}

int do_printf(char *buf, size_t maxlen, const char *fmt, va_list args)
{
	int len;
	unsigned long long num;
	int i;
	unsigned base;
	char *str;
	const char *s;

	int flags;				/* flags to number() */
	int field_width;		/* width of output field */
	unsigned precision;		/* min. digits (int); max. chars (string) */
	int qualifier;			/* 'h', 'l', or 'L' for integer fields */

	for (str=buf ; *fmt ; ++fmt) {
		if (*fmt != '%') {
			if (maxlen > 0) {
				printf_putchar(&str, *fmt);
				maxlen--;
			}
			continue;
		}
			
		/* process flags */
		flags = 0;
		repeat:
			++fmt;		/* this also skips first '%' */
			switch (*fmt) {
				case '-': flags |= LEFT; goto repeat;
				case '+': flags |= PLUS; goto repeat;
				case ' ': flags |= SPACE; goto repeat;
				case '#': flags |= SPECIAL; goto repeat;
				case '0': flags |= ZEROPAD; goto repeat;
				}
		
		/* get field width */
		field_width = -1;
		if ((*fmt >= '0') && (*fmt <= '9'))
			field_width = skip_atoi(&fmt);
		else if (*fmt == '*') {
			++fmt;
			/* it's the next argument */
			field_width = va_arg(args, int);
			if (field_width < 0) {
				field_width = -field_width;
				flags |= LEFT;
			}
		}

		/* get the precision */
		precision = UINT_MAX;
		if (*fmt == '.') {
			++fmt;	
			if ((*fmt >= '0') && (*fmt <= '9'))
				precision = skip_atoi(&fmt);
			else if (*fmt == '*') {
				++fmt;
				/* it's the next argument */
				precision = va_arg(args, unsigned int);
				if ((signed) precision < 0)
					precision = 0;
			}
		}

		/* get the conversion qualifier */
		qualifier = -1;
		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
			qualifier = *fmt;
			++fmt;
		}

		/* default base */
		base = 10;

		switch (*fmt) {
		case 'c':
			if (!(flags & LEFT))
				while ((--field_width > 0) && (maxlen > 0)) {
					printf_putchar(&str, ' ');
					maxlen--;
				}
			if (maxlen > 0) {
				printf_putchar(&str, (unsigned char) va_arg(args, int));
				maxlen--;
			}
			while ((--field_width > 0) && (maxlen > 0)) {
				printf_putchar(&str, ' ');
				maxlen--;
			}
			continue;

		case 's':
			s = va_arg(args, char *);
			if (!s)
				s = "<NULL>";

			len = strnlen(s, precision);

			if (!(flags & LEFT))
				while ((len < field_width--) && (maxlen > 0)) {
					printf_putchar(&str, ' ');
					maxlen--;
				}
			for (i = 0; (i < len) && (maxlen > 0); ++i) {
				printf_putchar(&str, *s++);
				maxlen--;
			}
			while ((len < field_width--) && (maxlen > 0)) {
				printf_putchar(&str, ' ');
				maxlen--;
			}
			continue;

		case 'n':
			if (qualifier == 'l') {
				long *ip = va_arg(args, long *);
				*ip = (str - buf);
			} else if (qualifier == 'L') {
				long long *ip = va_arg(args, long long *);
				*ip = (str - buf);
			} else {
				int *ip = va_arg(args, int *);
				*ip = (str - buf);
			}
			continue;

		/* integer number formats - set up the flags and "break" */
		case 'o':
			base = 8;
			break;

		case 'X':
			flags |= LARGE;
		case 'x':
			base = 16;
			break;

		case 'd':
		case 'i':
			flags |= SIGN;
		case 'u':
			break;

		case 'p':
			if (field_width == -1) {
				field_width = 2*sizeof(void *);
				flags |= ZEROPAD;
				flags &= ~SIGN;
			}
			qualifier = '@';
			base = 16;
			break;

		default:
			if ((*fmt != '%') && (maxlen > 0)) {
				printf_putchar(&str, '%');
				maxlen--;
			}
			if (*fmt) {
				if (maxlen > 0) {
					printf_putchar(&str, *fmt);
					maxlen--;
				}
			} else {
				--fmt;
			}
			continue;
		}
		if (qualifier == 'l') {
			if (flags & SIGN) {
				num = va_arg(args, long);
			} else {
				num = va_arg(args, unsigned long);
			}
		} else if (qualifier == 'L') {
			if (flags & SIGN) {
				num = va_arg(args, long long);
			} else {
				num = va_arg(args, unsigned long long);
			}
		} else if (qualifier == 'h') {
			if (flags & SIGN) {
				num = va_arg(args, int); /* promoted!!! */
			} else {
				num = va_arg(args, int); /* promoted!!! */
			}
		} else if (qualifier == '@') {
			/* Fake qualifier to fit %p formats into integer formats.  */
			num = (unsigned long)va_arg(args, void *);
		} else if (flags & SIGN) {
			num = va_arg(args, int);
		} else {
			num = va_arg(args, unsigned int);
		}
		number(&str, num, base, field_width, precision, flags, &maxlen);
	}
	if (maxlen > 0) {
		if (str != NULL) {
			*str = '\0';
		}
		maxlen--;
		return maxlen;
	} else {
		return -1;
	}
}


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2003-03-17 23:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-17 10:36 optimization/5477: gcc 3.0.x reserves a large stack frame, but uses only some parts of it Klaus Espenlaub
  -- strict thread matches above, loose matches on Subject: below --
2003-03-17 23:56 Wolfgang Bangerth
2003-03-15  4:38 bangerth
2002-01-24  1:06 espenlaub

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).