a strange infelicity of register allocation

Zack Weinberg zack@rabi.columbia.edu
Sat Jan 23 22:42:00 GMT 1999


Consider this loop:

char *p = buffer, *op = out_buffer;
for (;;)
{
    char c = *p++;
    switch (c)
    {
	case '\0':
	   goto out;
	case '\n':
	   /* stuff... */
	   break;
	case '\r':
	    /* similar stuff... */
	    break;
	case '?':
	   /* other stuff... */
	   break;
	default:
	   *op++ = c;
    }
}
out:

Where each special case is long and complicated.  Some of them re-use
the variable c for their own purposes, but the initial store to c is
dead at the beginning of each special case.

The code generated copies c = *p into a register, then out to a stack
slot.  It then does the switch based on the contents of the register.
Down in the default case, c is copied back in from the stack slot and
then written to memory.

If I move the default case to the top of the switch, so it begins like

switch (c)
{
    default:
	*op++ = c;
	break;

then c gets to stay in a register all the time, and the code runs
about twice as fast.  It seems to me we should be generating identical
code for both cases.

Platform is x86; problem was seen with both egcs 1.1.1 and the current
snapshot.  The actual code I'm talking about is the function
read_and_prescan in the patch for newline handling in cpplib which I
just posted.

zw



More information about the Gcc mailing list