Bug#463478: gcc-4.3: generates wrong code on i386 with -O3
Package: gcc-4.3
Version: 4.3-20080127-1
Severity: important
The attached code, coming from the GNU libc (test-ifloat.c and
s_cacoshf.c) gives wrong results when compiled with gcc-4.3 and -O3. The
results are correct with gcc-4.3 and lower optimisation or with gcc-4.2.
-- System Information:
Debian Release: lenny/sid
APT prefers unstable
APT policy: (500, 'unstable')
Architecture: i386
Kernel: Linux 2.6.18-5-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Versions of packages gcc-4.3 depends on:
ii binutils 2.18.1~cvs20080103-1 The GNU assembler, linker and bina
ii cpp-4.3 4.3-20080127-1 The GNU C preprocessor
ii gcc-4.3-base 4.3-20080127-1 The GNU Compiler Collection (base
ii libc6 2.7-6 GNU C Library: Shared libraries
ii libgcc1 1:4.3-20080127-1 GCC support library
ii libgmp3c2 2:4.2.2+dfsg-1 Multiprecision arithmetic library
ii libgomp1 4.3-20080127-1 GCC OpenMP (GOMP) support library
ii libmpfr1ldbl 2.3.0.dfsg.1-2 multiple precision floating-point
Versions of packages gcc-4.3 recommends:
ii libc6-dev 2.7-6 GNU C Library: Development Librari
-- no debconf information
/* gcc-4.3 -Wall -std=gnu99 -O3 -o test-cacoshf test-cacoshf.c */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <complex.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
__complex__ float
mycacoshf (__complex__ float x)
{
__complex__ float res;
int rcls = fpclassify (__real__ x);
int icls = fpclassify (__imag__ x);
if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
{
if (icls == FP_INFINITE)
{
__real__ res = HUGE_VALF;
if (rcls == FP_NAN)
__imag__ res = nanf ("");
else
__imag__ res = copysignf ((rcls == FP_INFINITE
? (__real__ x < 0.0
? M_PI - M_PI_4 : M_PI_4)
: M_PI_2), __imag__ x);
}
else if (rcls == FP_INFINITE)
{
__real__ res = HUGE_VALF;
if (icls >= FP_ZERO)
__imag__ res = copysignf (signbit (__real__ x) ? M_PI : 0.0,
__imag__ x);
else
__imag__ res = nanf ("");
}
else
{
__real__ res = nanf ("");
__imag__ res = nanf ("");
}
}
else if (rcls == FP_ZERO && icls == FP_ZERO)
{
__real__ res = 0.0;
__imag__ res = copysignf (M_PI_2, __imag__ x);
}
else
{
__complex__ float y;
__real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0;
__imag__ y = 2.0 * __real__ x * __imag__ x;
y = csqrtf (y);
if (__real__ x < 0.0)
y = -y;
__real__ y += __real__ x;
__imag__ y += __imag__ x;
res = clogf (y);
/* We have to use the positive branch. */
if (__real__ res < 0.0)
res = -res;
}
return res;
}
/* Various constants (we must supply them precalculated for accuracy). */
#define M_PI_34l (M_PIl - M_PI_4l) /* 3*pi/4 */
static float minus_zero, plus_zero, nan_value;
#define BUILD_COMPLEX(real, imag) \
({ __complex__ float __retval; \
__real__ __retval = (real); \
__imag__ __retval = (imag); \
__retval; })
#define MANT_DIG (FLT_MANT_DIG-1)
static void
check_float_internal (const char *test_name, float computed, float expected,
float max_ulp, int xfail)
{
int ok = 0;
float diff = 0;
float ulp = 0;
if (isnan (computed) && isnan (expected))
ok = 1;
else if (isinf (computed) && isinf (expected))
{
/* Test for sign of infinities. */
if (signbit (computed) != signbit (expected))
{
ok = 0;
printf ("infinity has wrong sign.\n");
}
else
ok = 1;
}
/* Don't calc ulp for NaNs or infinities. */
else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected))
ok = 0;
else
{
diff = fabsf (computed - expected);
/* ilogb (0) isn't allowed. */
if (expected == 0.0)
ulp = diff / ldexpf (1.0, - MANT_DIG);
else
ulp = diff / ldexpf (1.0, ilogbf (expected) - MANT_DIG);
if (computed == 0.0 && expected == 0.0
&& signbit(computed) != signbit (expected))
ok = 0;
else if (ulp <= 0.5 || (ulp <= max_ulp))
ok = 1;
else
ok = 0;
}
if (ok == xfail)
{
if (!ok)
printf ("Failure: ");
printf ("Test: %s\n", test_name);
printf ("Result:\n");
printf (" is: % .20e % .20a\n",
computed, computed);
printf (" should be: % .20e % .20a\n",
expected, expected);
}
}
static void
check_complex (const char *test_name, __complex__ float computed,
__complex__ float expected,
__complex__ float max_ulp, __complex__ int xfail)
{
float part_comp, part_exp, part_max_ulp;
int part_xfail;
char str[200];
sprintf (str, "Real part of: %s", test_name);
part_comp = __real__ computed;
part_exp = __real__ expected;
part_max_ulp = __real__ max_ulp;
part_xfail = __real__ xfail;
check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail);
sprintf (str, "Imaginary part of: %s", test_name);
part_comp = __imag__ computed;
part_exp = __imag__ expected;
part_max_ulp = __imag__ max_ulp;
part_xfail = __imag__ xfail;
check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail);
}
int main (int argc, char **argv)
{
plus_zero = 0.0;
nan_value = plus_zero / plus_zero;
minus_zero = copysignf (0.0, -1.0);
check_complex ("cacosh (0 + 0 i) == 0.0 + pi/2 i", mycacoshf (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0);
check_complex ("cacosh (-0 + 0 i) == 0.0 + pi/2 i", mycacoshf (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0);
check_complex ("cacosh (0 - 0 i) == 0.0 - pi/2 i", mycacoshf (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0);
check_complex ("cacosh (-0 - 0 i) == 0.0 - pi/2 i", mycacoshf (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0);
check_complex ("cacosh (-inf + inf i) == inf + 3/4 pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_34l), 0, 0);
check_complex ("cacosh (-inf - inf i) == inf - 3/4 pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_34l), 0, 0);
check_complex ("cacosh (inf + inf i) == inf + pi/4 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_4l), 0, 0);
check_complex ("cacosh (inf - inf i) == inf - pi/4 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_4l), 0, 0);
check_complex ("cacosh (-10.0 + inf i) == inf + pi/2 i", mycacoshf (BUILD_COMPLEX (-10.0, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_2l), 0, 0);
check_complex ("cacosh (-10.0 - inf i) == inf - pi/2 i", mycacoshf (BUILD_COMPLEX (-10.0, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_2l), 0, 0);
check_complex ("cacosh (0 + inf i) == inf + pi/2 i", mycacoshf (BUILD_COMPLEX (0, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_2l), 0, 0);
check_complex ("cacosh (0 - inf i) == inf - pi/2 i", mycacoshf (BUILD_COMPLEX (0, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_2l), 0, 0);
check_complex ("cacosh (0.1 + inf i) == inf + pi/2 i", mycacoshf (BUILD_COMPLEX (0.1L, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_2l), 0, 0);
check_complex ("cacosh (0.1 - inf i) == inf - pi/2 i", mycacoshf (BUILD_COMPLEX (0.1L, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_2l), 0, 0);
check_complex ("cacosh (-inf + 0 i) == inf + pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, 0)), BUILD_COMPLEX (HUGE_VALF, M_PIl), 0, 0);
check_complex ("cacosh (-inf - 0 i) == inf - pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, minus_zero)), BUILD_COMPLEX (HUGE_VALF, -M_PIl), 0, 0);
check_complex ("cacosh (-inf + 100 i) == inf + pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, 100)), BUILD_COMPLEX (HUGE_VALF, M_PIl), 0, 0);
check_complex ("cacosh (-inf - 100 i) == inf - pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, -100)), BUILD_COMPLEX (HUGE_VALF, -M_PIl), 0, 0);
check_complex ("cacosh (inf + 0 i) == inf + 0.0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, 0)), BUILD_COMPLEX (HUGE_VALF, 0.0), 0, 0);
check_complex ("cacosh (inf - 0 i) == inf - 0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, minus_zero)), BUILD_COMPLEX (HUGE_VALF, minus_zero), 0, 0);
check_complex ("cacosh (inf + 0.5 i) == inf + 0.0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, 0.5)), BUILD_COMPLEX (HUGE_VALF, 0.0), 0, 0);
check_complex ("cacosh (inf - 0.5 i) == inf - 0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, -0.5)), BUILD_COMPLEX (HUGE_VALF, minus_zero), 0, 0);
check_complex ("cacosh (inf + NaN i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, nan_value)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);
check_complex ("cacosh (-inf + NaN i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, nan_value)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);
check_complex ("cacosh (0 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
check_complex ("cacosh (-0 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
check_complex ("cacosh (NaN + inf i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);
check_complex ("cacosh (NaN - inf i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);
check_complex ("cacosh (10.5 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
check_complex ("cacosh (-10.5 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (-10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
check_complex ("cacosh (NaN + 0.75 i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, 0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
check_complex ("cacosh (NaN - 0.75 i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, -0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
check_complex ("cacosh (NaN + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
return 0;
}
Reply to: