Bug 36124 - conditional loop becomes infinite loop in -O2 (gcc 4.2 -> 4.3 regression)
Summary: conditional loop becomes infinite loop in -O2 (gcc 4.2 -> 4.3 regression)
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.3.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 36232 (view as bug list)
Depends on:
Blocks:
 
Reported: 2008-05-04 16:25 UTC by Cyprien Laplace
Modified: 2008-05-13 21:26 UTC (History)
3 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Cyprien Laplace 2008-05-04 16:25:20 UTC
Hi,

It seems to have some regression in gcc 4.3, visible on arm targets as well as x86_64.
I originally already reported it to Debian bugtracking system [http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=472867]

I tested it against the latest gcc snapshot:
    gcc (GCC) 4.3.1 20080501 (prerelease)

gcc has been built with no option, only srcdir/configure && make.

preprocessed content:
# 1 "c.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "c.c"


extern void func(void*);

void test()
{
    register long *foo = (long*) 1024;
    register int index;
    for(index=0;index<1024;index++)
        func(foo--);
}


This is a simple loop indexed on an integer. It should be finite, but when compiling with -O2 (and -O3) the compiler removes the end condition.

gcc -S -O2 extract:
.LCFI0: 
        movl    $1024, %edi
        .p2align 4,,10
        .p2align 3
.L2:
        leaq    -8(%rdi), %rbx
        call    func
        movq    %rbx, %rdi
        jmp     .L2


Note that when using char* or non-pointer type for foo variable, it compiles successfully.
Comment 1 Andrew Pinski 2008-05-04 16:34:41 UTC
Pointers types overflow is undefined which is what you are seeing.
Comment 2 Cyprien Laplace 2008-05-04 16:41:22 UTC
shouldn't gcc report a warning in this case ?

because silently entering an infinite loop is not very kind...
Comment 3 Andrew Pinski 2008-05-04 16:45:07 UTC
(In reply to comment #2)
> shouldn't gcc report a warning in this case ?

Maybe, but really depending on undefined behavior is bad too. 
Comment 4 kargls 2008-05-04 17:01:19 UTC
(In reply to comment #2)
> shouldn't gcc report a warning in this case ?
> 
> because silently entering an infinite loop is not very kind...
> 

If your code invokes undefined behavior, how is gcc going
to read your mind?  Maybe the programmer meant to enter
an infinite, so a warning isn't correct.
Comment 5 Cyprien Laplace 2008-05-04 17:03:39 UTC
Now, this code should not rely on undefined behaviour:

extern void func(int,void*);
void test()
{
    register long *foo = (long*) (4*sizeof(*foo)) - 1;
    register int index;
    for(index=0;index<4;index++)
        func(index,foo--);
}


it still make an infinite loop, while last func call is done with foo parameter (nil).


Do you mean I explicitely ask gcc to use foo as end-of-loop condition ??
Comment 6 Andrew Pinski 2008-05-04 17:09:28 UTC
>Now, this code should not rely on undefined behaviour:

It does because incrementing or decrementing to a NULL Pointer is undefined.
Comment 7 Cyprien Laplace 2008-05-04 17:31:14 UTC
it's right, using --foo unstead of foo-- gives a better result.
But it does not make me happy (about the possibility of a bug)
Comment 8 Cyprien Laplace 2008-05-04 20:13:11 UTC
On some embedded machines, the SDRAM lays on 0x00000000 address. So it is not so meaningless to increment or decrement from/to NULL pointer.
Comment 9 Richard Biener 2008-05-07 19:42:52 UTC
decrementing a NULL pointer invokes undefined behavior, incrementing not.
Comment 10 Andrew Pinski 2008-05-13 20:02:03 UTC
*** Bug 36232 has been marked as a duplicate of this bug. ***
Comment 11 Scott wood 2008-05-13 21:13:56 UTC
(In reply to comment #4)
> If your code invokes undefined behavior, how is gcc going
> to read your mind?

If GCC can tell that it is undefined behavior, then warning the user is more useful than silently producing nasal demons, regardless of what might be in the user's mind.  "The spec allows us to do something stupid" doesn't mean "we should do something stupid".

> Maybe the programmer meant to enter
> an infinite, so a warning isn't correct.

If it's undefined behavior, then too bad, right?  I have a really hard time seeing how one would derive such intent from the above code, though -- or imagining what GCC is doing that made it think that generating the code it does is a good idea.