Bug 30599 - long double declaration rounds to double instead
Summary: long double declaration rounds to double instead
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-26 16:20 UTC by R. Clint Whaley
Modified: 2007-06-21 09:15 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Can be compiled to .s as described in report to duplicate error (298 bytes, text/plain)
2007-01-26 16:21 UTC, R. Clint Whaley
Details

Note You need to log in before you can comment on or make changes to this bug.
Description R. Clint Whaley 2007-01-26 16:20:11 UTC
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
Comment 1 R. Clint Whaley 2007-01-26 16:21:45 UTC
Created attachment 12963 [details]
Can be compiled to .s as described in report to duplicate error
Comment 2 Andrew Pinski 2007-01-26 17:49:36 UTC
Use sqrtl then if you don't want the rounding.
Comment 3 R. Clint Whaley 2007-06-20 21:52:11 UTC
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.
Comment 4 Andrew Pinski 2007-06-20 22:04:40 UTC
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.
Comment 5 R. Clint Whaley 2007-06-20 22:17:02 UTC
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.
Comment 6 R. Clint Whaley 2007-06-20 23:17:11 UTC
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
Comment 7 Danny Smith 2007-06-20 23:32:09 UTC
(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

Comment 8 Andrew Pinski 2007-06-21 09:15:23 UTC
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.