From Bugzilla Helper: User-Agent: Mozilla/4.76 [en] (X11; U; SunOS 5.8 sun4m) Description of problem: math library functions for double precision arguments can produce subnormal numbers even when -mieee is not specified. when these are passed on to the hardware, they cause a crash on a floating exception How reproducible: Always Steps to Reproduce: 1. gcc bug3.c -lm 2. a.out 3. Actual Results: result 1a: 1.175494e-38 -8.733655e+01 result 1b: 0.000000e+00 result 1c: 0.000000e+00 result 2a: 2.225074e-308 -7.083964e+02 result 2b: 1.349576e-308 Floating exception Expected Results: result 1a: 1.175494e-38 -8.733655e+01 result 1b: 0.000000e+00 result 1c: 0.000000e+00 result 2a: 2.225074e-308 -7.083964e+02 result 2b: 0.000000e+00 result 2c: 0.000000e+00 result 3a: 2.225074e-308 -7.083964e+02 result 3b: 0.000000e+00 result 3c: 0.000000e+00 Additional info: the math library behaves correctly for single precision arguments, the bug is only triggered when double precision arguments are passed. long doubles are treated the same as doubles by gcc on this machine and may be ignored. result 2a shows DBL_MIN and the natural logarithm of that number result 2b in the Actual Results shows a subnormal number: exp(log(DBL_MIN)-0.5), it should have underflowed to zero, as is shown in the Expected Results (which were obtained using ccc instead of gcc on the same computer). The subnormal number is passed on to the hardware to be multiplied by 2, which causes the Floating exception. bug3.c can be obtained from the URL listed above, and will be attached to this report as well.
Created attachment 26538 [details] bug3.c: sample program that triggers the bug
There is just one libm, not a separate one for non-mieee and -mieee. The reason why your program does not fail for float is that you don't call logf or expf but log resp. exp, so the caller has to convert them to float from double and thus flush to zero happens. I think it is a bug in the program if you are doing something which results in subnormal numbers and are not compiling with -mieee (the whole distribution uses this flag on alpha), at least I don't think it is worthy to have 2 different libm libraries and multilib them (and there is obviously a need for libm which gives precise results). I'll let Richard comment on this though...
Let me point out that I do not want to use subnormal number at all ! I compile without the -mieee flag because that gives more efficient code and that is exactly what I want. I am perfectly happy to live with the resulting abrupt underflow. However, I find that the math library forces the subnormal numbers onto me anyway, and then the compiler handles the results incorrectly by passing the subnormal numbers directly to the hardware which doesn't support them and causes the program to crash. Whatever computing standard you support, the simple test case I supplied should never crash. It should either result in an underflow to zero, or to a subnormal number, but not a floating exception. I am doing nothing illegal or inappropriate in that code. Let me also point out that the IEEE standard is NOT intended to give more precise results, it is intended give more standardized behaviour across various platforms. However, on machines which do not support gradual underflow in hardware (such as the alpha chip) that comes at a significant price in terms of computing speed. My personal opinion is (and I am aware that I may not be speaking for everybody here) that this kind of degradation in computing speed should not be forced on the user. PS - The attached program doesn't work correctly with -mieee either, but I guess that is a separate bug....
If you want denormals to underflow, I suggest you set FE_MAP_DMZ and FE_MAP_UMZ in the floating point environment. This can be done with fesetenv(FE_NONIEEE_ENV). On EV6 machines, the flush to zero is then handled in hardware. For earlier machines, you'll need something like this: static inline double flush_to_zero(double x) { #ifndef __alpha_ev6__ double exp; asm ("cpyse %2,$f31,%1; cpys %2,$f31,%0; fcmovne %1,%2,%0" : "=&f"(x), "=&f"(exp) : "f"(x)); #endif return x; } to be used like so result = flush_to_zero(exp(x)); I agree that it would be nice if this all sort of happened automatically with libm, but that's not likely to happen overnight, or even soon. Oh, there's also the DEC cpml library, which in addition to havling faster versions of some math routines, also may flush to zero by default. See ftp://ftp.compaq.com/pub/products/C-CXX/linux/compaq_c
I was able to get correct behaviour of the code using fesetenv(FE_NONIEEE_ENV) on EV56 hardware. Thanks for the work-around ! Linking the gcc code against the Compaq math library (-lcpml) also works fine. It flushes to zero by default and is also faster than the standard math library. However, if you have the Compaq math library, chances are that you have a working ccc compiler as well. In that case I would advise to use ccc since it gives faster code than gcc (at least for my program) and gives correct behaviour by default.
There is no point in keeping this bug open. Red Hat will not actively work on any Alpha issue. And the glibc maintainers also have not much interest in doing this work. If you still want to see this working as you expect it you'll probably have to come up with a patch yourself and send it to the glibc lists.