This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Bug in code generation of gcc-2.95.2


Consider the following code:

char *Picklist[8];
int func()
{
	int i;

	i = 0;
	while (i < 7) {
		Picklist[i] = Picklist[i+1];
		i++;
	}
	return 0;
}
The code generated for this loop by gcc is:
	movl	$04b0940,%ecx	(puts PickList in ecx)
	movl	$0x1,%edx	(index, starts at one)
loop:
	movl	(%ecx,%edx,4),%eax  (puts Picklist[i+1] in eax)
	movl	%eax,-4(%ecx,%edx)  (puts eax into Picklist[i])
	leal	0x1(%edx),%edi      (increments edx into edi)
	movl	%edi,%edx           (copies into edx the incremented value)
	cmpl	$0x6,%edx           (HERE IS THE BUG!!!!!!!!!)
	jle	loop

Gcc is optimizing the access to the table, using a loop counter starting at
1 instead of zero. This could be quite ok, but gcc forgets to increment the
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
integer at the end of the test!!! This loop is copying
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	Picklist[5] = Picklist[6]
as the LAST copy, instead of the correct
	Picklist[6] = Picklist[7]
as SPECIFIED IN THE C Code!!!

If you pre-increment the loop index, then you should increment the boundary
test too, if not, as this is the case with the shown C code, the generated code
fails to copy the last element of the array.

When I replace the above loop by the equivalent:
	memmove(PickList,&PickList[1],(MAXPICKLIST-1)*sizeof(char *));
	PickList[MAXPICKLIST-1] = p;

Everything is OK, no bugs, no crashes.

If I do not specify any optimizations, the bug goes away of course.

This bug doesn't appear in the code snippet above, but only in certain
circumstances, i.e. when not all registers are available, etc etc. 
The optimization level I used -O2.
------------------------------------------------------------------cut here
Here is a code snippet that will demonstrate the bug:
#define MAXPICKLIST 8
char *PickList[MAXPICKLIST];
int ReadOpen(char *fn, int historyflag)
{
        char *p;
        int i, j;

        p = "Something";
        i = 0;
        while (i < MAXPICKLIST) {
                if (PickList[i] == (char *)0) {
                        PickList[i] = p;
                        break;
                }
                i++;
        }
        if (i == MAXPICKLIST) {
                release(PickList[0]);
                i = 0;
                /* The last assignment that this code specifies is
                PickList[MAXPICKLIST-2] = PickList[MAXPICKLIST-1] or, in
                numbers:
                PickList[6] = PickList[7]
                This is not respected in the generated code */
                while (i < MAXPICKLIST - 1) {
                        PickList[i] = PickList[i + 1];
                        i++;
                }
                PickList[i] = p;
        }
        return (0);
}
---------------------------------------------------------------cut here
Compile this with
gcc -O2 -c -S test.c
You will obtain the assembler where the bug is obvious (look at the 
initialization of edx to one, near the end of the function).
-- 
Jacob Navia	Logiciels/Informatique
41 rue Maurice Ravel			Tel 01 48.23.51.44
93430 Villetaneuse 			Fax 01 48.23.95.39
France

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]