Bug#322218: gcc -O2 optimization bug
Package: gcc
Version: 3.3.5-3
When compiled with -O2, the appended test program goes into an
infinite loop at run-time. When compiled with -O or with no
optimization, it runs correctly, exiting immediately and
generating no output.
I am using Debian GNU/Linux 3.1, with a 2.4.28 kernel and
libc6-2.3.2.ds1-22
#include <math.h>
#include <float.h>
#include <stdio.h>
/* gcc optimization bug
 *
 * Problem:  Program goes into an infinite loop when
 *           compiled with -O2 optimization.
 *
 * compile:  gcc $OPT bug.c -lm
 *     run:  ./a.out
 *
 * gcc -O  bug.c -lm   => works with 2.95.4, 3.3.5, 3.4.4, 4.0.0
 * gcc -O2 bug.c -lm   => infinite loop with 3.3.5 and 3.4.4
 *                     => works with 2.95.4 and 4.0.0
 */
static int bisection (double (*func)(double, void *), double a, double b, void *cd, double *xp)
{
   unsigned int count = 1;
   unsigned int bisect_count = 5;
   double fa, fb;
   double x = a;
   if (a > b)
     {
        double tmp = a; a = b; b = tmp;
     }
   fa = (*func)(a, cd);
   fb = (*func)(b, cd);
   if (fa * fb > 0)
     {
        *xp = a;
        return -1;
     }
   while (b > a)
     {
        double fx;
        if (fb == 0.0)
          {
             x = b;
             break;
          }
        if (fa == 0.0)
          {
             x = a;
             break;
          }
        if (count % bisect_count)
          {
             x = (a*fb - b*fa) / (fb - fa);
             if ((x <= a) || (x >= b))
               x = 0.5 * (a + b);
          }
        else
          x = 0.5 * (a + b);
        if ((x <= a) || (x >= b))
          break;
        fx = (*func)(x, cd);
        count++;
        if (fx*fa < 0.0)
          {
             fb = fx;
             b = x;
          }
        else
          {
             fa = fx;
             a = x;
          }
     }
   *xp = x;
   return 0;
}
static double f (double x, void *cd)
{
   (void) cd;
   return x - cos(x);
}
int main (void)
{
   double x;
   (void) bisection (&f, 0.0, 1.0, NULL, &x);
   if (fabs(f(x,NULL)) > DBL_EPSILON)
     fprintf (stdout, "Error\n");
   return 0;
}
Reply to: