public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* confused at code generation for a empty loop
@ 2007-11-30  7:16 PRC
  2007-11-30 10:13 ` kum
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: PRC @ 2007-11-30  7:16 UTC (permalink / raw)
  To: gcc-help

Here is my code:
=================================================================================
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 1
static int flag = 0;
void *thread(void *threadid)
{
    int ret = rand();
    printf("thread return %d!\n", ret);
    sleep(10);
    flag = 1;
    return (void *)ret;
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   rc = pthread_create(&threads[0], NULL, thread, (void *)0);
   if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
   }
   while( flag == 0 ) ;
   return 0;
}
=================================================================================
gcc -O2 -g -lpthread a.c
objdump -S a.out > a.S


`cat a.S` shows:
=================================================================================
   if (rc){
 80484d4:   85 c0                   test   %eax,%eax
 80484d6:   75 15                   jne    80484ed <main+0x4d>
 80484d8:   a1 68 97 04 08          mov    0x8049768,%eax
 80484dd:   85 c0                   test   %eax,%eax
 80484df:   90                      nop
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
   }
   while( flag == 0 ) ;
 80484e0:   74 fe                   je     80484e0 <main+0x40>
================================================================================
You can see the variable `flag` is read only once. If the value of `flag` is 0 at the first time, 
the program will trap into a dead loop and never exit. And gcc knows the value of `flag` could
be modified in the routine `thread`.


But if I modify the line "while( flag == 0 ) ;" to "while(flag == 0) printf("waiting..\n");"
and recompile the source code, the output assembly code becomes:
=================================================================================
while( flag == 0 ) printf("waiting..\n");
 8048510:   c7 04 24 74 86 04 08    movl   $0x8048674,(%esp)
 8048517:   e8 90 fe ff ff          call   80483ac <puts@plt>
 804851c:   a1 b8 97 04 08          mov    0x80497b8,%eax
 8048521:   85 c0                   test   %eax,%eax
 8048523:   74 eb                   je     8048510 <main+0x40>
=================================================================================
`flag` is read in each loop. Then when the value of `flag` is modified, the loop terminates.

I wonder why gcc generates code for a empty loop like that. Is it a bug or for optimization in some case?

My gcc is:
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)

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

* Re: confused at code generation for a empty loop
  2007-11-30  7:16 confused at code generation for a empty loop PRC
@ 2007-11-30 10:13 ` kum
  2007-11-30 10:51 ` Marco Manfredini
  2007-11-30 14:49 ` Tim Prince
  2 siblings, 0 replies; 5+ messages in thread
From: kum @ 2007-11-30 10:13 UTC (permalink / raw)
  To: PRC; +Cc: gcc-help

while you use
static int flag = 0;
gcc is free to read the flag only once (optimisation) in any loop. To
inform this to the compiler you have to make use of volatile type
modifier. This will force the compiler to load the flag every time it
tests it.

By the way using some synch object (like semaphore) you can do the
same job better.

-kum

On Nov 30, 2007 12:15 PM, PRC <panruochen@gmail.com> wrote:
> Here is my code:
> =================================================================================
> #include <pthread.h>
> #include <stdio.h>
> #define NUM_THREADS 1
> static int flag = 0;
> void *thread(void *threadid)
> {
>     int ret = rand();
>     printf("thread return %d!\n", ret);
>     sleep(10);
>     flag = 1;
>     return (void *)ret;
> }
>
> int main (int argc, char *argv[])
> {
>    pthread_t threads[NUM_THREADS];
>    int rc;
>    rc = pthread_create(&threads[0], NULL, thread, (void *)0);
>    if (rc){
>          printf("ERROR; return code from pthread_create() is %d\n", rc);
>          exit(-1);
>    }
>    while( flag == 0 ) ;
>    return 0;
> }
> =================================================================================
> gcc -O2 -g -lpthread a.c
> objdump -S a.out > a.S
>
>
> `cat a.S` shows:
> =================================================================================
>    if (rc){
>  80484d4:   85 c0                   test   %eax,%eax
>  80484d6:   75 15                   jne    80484ed <main+0x4d>
>  80484d8:   a1 68 97 04 08          mov    0x8049768,%eax
>  80484dd:   85 c0                   test   %eax,%eax
>  80484df:   90                      nop
>          printf("ERROR; return code from pthread_create() is %d\n", rc);
>          exit(-1);
>    }
>    while( flag == 0 ) ;
>  80484e0:   74 fe                   je     80484e0 <main+0x40>
> ================================================================================
> You can see the variable `flag` is read only once. If the value of `flag` is 0 at the first time,
> the program will trap into a dead loop and never exit. And gcc knows the value of `flag` could
> be modified in the routine `thread`.
>
>
> But if I modify the line "while( flag == 0 ) ;" to "while(flag == 0) printf("waiting..\n");"
> and recompile the source code, the output assembly code becomes:
> =================================================================================
> while( flag == 0 ) printf("waiting..\n");
>  8048510:   c7 04 24 74 86 04 08    movl   $0x8048674,(%esp)
>  8048517:   e8 90 fe ff ff          call   80483ac <puts@plt>
>  804851c:   a1 b8 97 04 08          mov    0x80497b8,%eax
>  8048521:   85 c0                   test   %eax,%eax
>  8048523:   74 eb                   je     8048510 <main+0x40>
> =================================================================================
> `flag` is read in each loop. Then when the value of `flag` is modified, the loop terminates.
>
> I wonder why gcc generates code for a empty loop like that. Is it a bug or for optimization in some case?
>
> My gcc is:
> Using built-in specs.
> Target: i386-redhat-linux
> Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
> Thread model: posix
> gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)
>
>

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

* Re: confused at code generation for a empty loop
  2007-11-30  7:16 confused at code generation for a empty loop PRC
  2007-11-30 10:13 ` kum
@ 2007-11-30 10:51 ` Marco Manfredini
  2007-11-30 14:49 ` Tim Prince
  2 siblings, 0 replies; 5+ messages in thread
From: Marco Manfredini @ 2007-11-30 10:51 UTC (permalink / raw)
  To: gcc-help

On Friday 30 November 2007 07:45, PRC wrote:

> static int flag = 0;
[thread writes to flag]

[meanwhile in parent thread]
>    while( flag == 0 ) ;

There's no way for gcc to tell, that your thread will change "flag", so gcc 
assumes it stays the same. gcc doesn't know what pthread_create does.

> But if I modify the line "while( flag == 0 ) ;" to "while(flag == 0)
> printf("waiting..\n");"

Now gcc has no way to tell, that "printf" will *not* change "flag" somehow, so 
gcc rereads "flag" 

Add a "volatile" modifier to "flag" to inform gcc that "flag" may change at 
any moment.


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

* Re: confused at code generation for a empty loop
  2007-11-30  7:16 confused at code generation for a empty loop PRC
  2007-11-30 10:13 ` kum
  2007-11-30 10:51 ` Marco Manfredini
@ 2007-11-30 14:49 ` Tim Prince
  2007-11-30 18:37   ` Marco Manfredini
  2 siblings, 1 reply; 5+ messages in thread
From: Tim Prince @ 2007-11-30 14:49 UTC (permalink / raw)
  To: PRC; +Cc: gcc-help

PRC wrote:

>    while( flag == 0 ) ;

> I wonder why gcc generates code for a empty loop like that. Is it a bug or for optimization in some case?
> 
This subject has been debated at length, and some programmers rely on
the current gcc treatment.  More programmers rely on loops whose exit
condition should not be optimized away, but does get "optimized" away by
unsafe "optimizations" by certain compilers, including gcc -ffast-math.

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

* Re: confused at code generation for a empty loop
  2007-11-30 14:49 ` Tim Prince
@ 2007-11-30 18:37   ` Marco Manfredini
  0 siblings, 0 replies; 5+ messages in thread
From: Marco Manfredini @ 2007-11-30 18:37 UTC (permalink / raw)
  To: gcc-help

On Friday 30 November 2007 15:17, Tim Prince wrote:
> PRC wrote:
> >    while( flag == 0 ) ;
> >
> > I wonder why gcc generates code for a empty loop like that. Is it a bug
> > or for optimization in some case?
>
> This subject has been debated at length, and some programmers rely on
> the current gcc treatment.  More programmers rely on loops whose exit
> condition should not be optimized away, but does get "optimized" away by
> unsafe "optimizations" by certain compilers, including gcc -ffast-math.

A programmer who writes code whose correctness relies on certain properties of 
the optimizer isn't worth the money he wants you to pay him. A programmer 
should rely on the specified semantics of the language he's using. C and C++ 
both assume, that the program flow is the only source of side effects, unless 
told otherwise. "volatile" is the tool to advise the compiler that additional 
mutators exist and that these mutators will produce side effects in a 
specified memory locations. End of story.

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

end of thread, other threads:[~2007-11-30 17:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-30  7:16 confused at code generation for a empty loop PRC
2007-11-30 10:13 ` kum
2007-11-30 10:51 ` Marco Manfredini
2007-11-30 14:49 ` Tim Prince
2007-11-30 18:37   ` Marco Manfredini

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).