This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Bad optimization of a function pointer call with GCC 2.8.1
- To: <bug-gcc at gnu dot org>, <support at wrs dot com>, <richard dot lopez at ada dot com>, <roger dot byelick at ada dot com>
- Subject: Bad optimization of a function pointer call with GCC 2.8.1
- From: Jeff Byers <jeff dot byers at ada dot com>
- Date: Wed, 22 Sep 1999 10:40:24 -0700
- Cc: <jlbyers at san dot rr dot com>, <derek dot nelson at ada dot com>, <darrell dot smith at ada dot com>
/*********************************************************************
Bad loop-invariant optimization of a function pointer call with GCC
2.8.1.
The following code, when compiled using the GCC compiler version 2.8.1 with
optimization level -O1 or greater, generates incorrect code.
With the work-around disabled, fputc('*', stdout) is only called once
instead of 10 times. The function pointed to by *fp_fputc should be called
on each pass through the loop, but it is pulled out of the loop, and
called only once which is wrong.
A work-around is to volatize a fp_fputc argument. It is unclear why this
work-around is successful as the variable being volatized should make no
difference to the optimizer -- the variable is a local automatic, address
is not shared, etc. But it does work.
Running optimization level -O0 is another work-around.
Problem is seen with target machines: Motorola MPC860, SUN Sparc
Compile: gcc -O1 -g -o gcc_fpopt_bug gcc_fpopt_bug.c
Run: ./gcc_fpopt_bug
- Jeff Byers - jeff.byers@ada.com -
**********************************************************************/
/* gcc_fpopt_bug.c */
#include <stdio.h>
#ifndef USE_WORK_AROUND
#define USE_WORK_AROUND 0
#endif
typedef int tfd_fputc(int, FILE *);
static int
padit(int n, int c, const tfd_fputc *fp_putc, FILE *pFile)
{
volatile int vol_c = c; // For work-around.
while ( n-- > 0 )
{
# if (!USE_WORK_AROUND)
if ( ((*fp_putc)( c, pFile )) != c )
# else
if ( ((*fp_putc)( vol_c, pFile )) != c )
# endif
return( 1 );
}
return( 0 );
}
int main(char *argv[], int argc)
{
printf("Should see 10 '*'s, - %susing work-around.\n",
USE_WORK_AROUND ? " " : "not ");
padit( 10, '*', (const tfd_fputc *)fputc, stdout );
printf("\nDone.\n");
return(0);
}