Hi, Since bug 30255 has been declared as never going to be fixed, I've been enjoying going through half a million lines of code looking for places where I have to declare things long double to keep gcc from arbitrarily rounding down intermediate results. The problem now is that I have come across a case where the exact opposite occurs: If I declare a variable long double, gcc inserts a round to double before computing the square root, where it does not if I declare it double. I will upload the file seperately, but here's the section of code: for (i=0; i < N; i++) t0 += X[i]*X[i]; t0 = sqrt(t0); When compiled with t0 declared as double, no spills are performed by gcc, and 80-bit accuracy is maintained throughout the computation (critical to avoid overflow). When declared as long double, however, the following code is inserted: fstpl 16(%rsp) fldl 16(%rsp) fld %st(0) fsqrt So, a long double is rounded to double by gcc, even though there is no store in the algorithm. Any idea what is going on, and is there anything to be done? I will post the short file seperately. You can gen both assemblies to see the difference with gcc -O -mfpmath=387 -S nrm2.c # gen double declaration gcc -O -mfpmath=387 -DLD_ -S nrm2.c # gen long double variant Thanks, Clint
Created attachment 12963 [details] Can be compiled to .s as described in report to duplicate error
Use sqrtl then if you don't want the rounding.
Turns out the proposed solution of using sqrtl is not portable. In particular, all code using it fails to link on Windows using cygwin. Any idea how to make this work portably? I still don't understand why it is OK for a double accumulator to get an 80-bit sqrt, whereas a long double accumulator gets rounded.
sqrtl is C99 so it is portable, just not to cygwin. That is not our fault that cygwin does not provide a C99 math library.
It may be C99, but since it doesn't work on 90% of the machines in the world, it is a bit of a stretch to call it portable. My point is no standard mandates you round down a long double (where you don't round down a double), and that would provide a solution that *would* port to cygwin. So I ask again, why do you need to round down a long double, but not a double accumulator? Note that none of this would be necessary if gcc didn't randomly round down doubles upon spills; remember that I switched to long double because *you* declared it to be a solution since you did not plan to fix the original spill/rounding bug. I am trying to get a math library working portably despite these problems, but it seems I'm going to be prevented by interdependent gcc bugs that will never be fixed.
Anybody have enough __asm__ foo to write a inline assembly macro taking a long double operand and returning one, which I can use to call fsqrt directly in inline assembly? I'm scoping the docs, but have never found inline assembly constraints that intuitive, and with the need for x87 registers on the stack, less so. If I can write such a macro, I can call it on Windows instead of sqrtl. The long double accumulator is on the stack, fsqrt takes a stack arg, so it should be easy to do, I would think . . . Thanks, Clint
(In reply to comment #6) > Anybody have enough __asm__ foo to write a inline assembly macro taking a long > double operand and returning one, which I can use to call fsqrt directly in > inline assembly? http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/mingw/mingwex/math/sqrtl.c?cvsroot=src should help. You could use __builtin_nan to replace the external reference Danny
But again, even if sqrtl is not part of the library, this is not a GCC issue. We provide builtins for faster usage and not to get around libc not including the function.