This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Floating-point Consistency, -ffloat-store, and x86 (mostly)


>However, I don't understand why you claim that leaving the CPU in 64
>bit mode would be problematic.

Maybe it wouldn't, but I'm quite pessimistic about any change that
makes the CPU behave differently than what other programmers,
who through some means created .o and .a files to which newly
compiled modules (that set the CPU to the different behavior)
link to before invoking the code in them, expect.

>It would seem to me that the only code that would appropriately rely
>on the registers being extended precision would have to be either hand
>written assembler or *extremely* carefully written code in a higher
>level language.  I'd think that anyone capable of doing this would
>also be cognizant of the issues involved & quite capable of saving,
>setting & restoring the FPU control word appropriately.

If we were designing a new architecture from scratch, along with the
whole toolchain (assemblers, libraries, linkers, object-file formats,
and so on), I'd be less concerned, and just work hard to make sure
we made all the appropriate facilities available and documented the
bajeebers out of the issues.

But, keep in mind that, as someone else pointed out, there are
plenty of people *already* happy with the present situation, or
at least (as I worry :) who *think* they're happy with it.

That is, their code uses 80-bit precision, and they either don't
care, or expected it but don't have, or haven't yet noticed ill
effects from, any 64-bit spills of 80-bit values.

Now, for those who expected that 80-bit precision, which they got
for "free" on x86 machines without having to make any changes
(probably) in their code...

...what do you think they'll say when, upon using the "new gcc"
that sets the FPU to 64-bit mode, their code suddenly goes into
64-bit mode -- even their code that was compiled with the "old gcc"?

I think they'll be really upset.

To me, this is kind of like the issue of 64-bit double alignment
on the stack.  (To do it right, we need cooperation from crtN
through main() all the way down the call chain, at least to the
leafs, defined as procedures that don't call any FP-using
procedures.  That is, making sure the last several bits of the
frame pointer are "universally" zero is basically an exercise similar to
making sure the FP mode is universally 64-bit, in that it requires
some mixture of cooperation and defensiveness during code
generation to get it always right.)

Only difference is, mix up .o's, .a's, and different compiler
invocations, and with the 64-bit double alignment issue you get
flaky timing...

...whereas, with the 64-bit-mode FPU issue, you get flaky numerics.

Given that I'm still a bit worried about the alignment/performance
issue, you can understand why I simply cannot propose, or endorse
any proposal, that we simply decide the FPU on x86 machines (and
similar) be placed in 64-bit mode and hand-wave whatever problems
that might expose down the road.

>So, I don't see why you're claiming that the FPU control word would
>have to be fiddled on the fly according to embedded object code
>notations.

See the above.  In short, each snippet of code, at no more than a
procedure-level boundary, has its own requirements, or lack thereof,
regarding the precision of the FPU.

AFAIK, for *all* existing x86 code, once it reaches the .s, .o, .a,
.so, or executable, stage, there is *no way* to recover those
requirements, which I believe can currently exist only as commentary
in the code, if we're even that lucky.

We can't assume "prevailing mode acceptable" is going to work for
all existing code out there, and the danger gets worse as the
percentage for which it doesn't goes *down*, until it reaches zero,
because the lower that percentage, the more changes people will
trust the executable that links in the rare code that expected
80-bit mode on the grounds that "this has always worked before",
and thus not be suspicious of what turns out to be wrong answers.

>Also, you said that leaving the FPU in 64 bit mode isn't a full
>solution because of double rounding.  It seems to me that the double
>rounding is only an issue near the edges of the range of a double, and
>as such is also a small problem.

I've seen that claimed by others discussing this issue vis-a-vis
Java and x86 numerics, but IIRC it isn't 64-bit-mode that does the
double rounding, it's 80-bit-mode with continual 64-bit store/reload.
At least, I think that's what they were talking about.

I *think* 64-bit mode doesn't suffer from double rounding.  I think
what it suffers from is greater exponent range than IEEE 64-bit doubles
really provide, until (of course) spills to memory happen.  We
should definitely study these alternatives, with an eye to determining
whether the rest of the industry will find acceptable, before assuming
we can just set the FPU to whatever mode we like.

>After all, one thing that people
>expect from floating point math is trailing garbage, and this would
>just be another example - another check on the paranoia tests.

That might be right, but it'll worry me until the numerical big-wigs
come out and say it.  And, again, I think it's only a problem for
-ffloat-store-like store/reloads (FPU in 80-bit mode).

>I think the biggest problem is the places where the underlying
>extended precision registers are exposed to programmer.

That, and, 64-bit-mode FPU doesn't sound promising vis-a-vis
32-bit operations.  Either the FPU must be switched back and forth
among the two modes (32 and 64), which is, apparently, dog slow
on current chips, or we get right back into the double-rounding
and exponent-range problems, perhaps the spill-with-chopping
problem, as well.

That is, putting the FPU into 64-bit mode, AFAICT, gives us an
enticingly "cheap" way to say "see, now all those 64-bit calculations
will be nearly strict IEEE", but will have done basically nothing
for the 32-bit calculations, which I think will still be a problem
(as compared to other machines -- at least some of them, anyway,
do real IEEE 32-bit operations, I'm pretty sure).

>There's no way for a programmer in a higher level language to
>currently get at the values in the extended precision registers, nor
>is there a way to explicitely use them.  However, their existence is
>exposed by comparison operations.  This is what leads to all sorts of
>insanities such as 1.0/3.0 != 1.0/3.0 (when done appropriately with
>variables).

Yup.  Though some compilers (some of Digital's, I think) support
explicit extended-type declarations (REAL*10 in Fortran, as I think
I posted about already last week or so), "we" (gcc) don't yet.

>This is why I think the best thing would be to just default the FPU to
>double precision (not extended precision) mode, or at least make it
>easily settable.  It removes the difference between comparing
>registers & memory, and makes numerics as register vs memory usage
>independent as they can be on an ix86 in a higher level language.

I agree we should make it easily settable, but I think we'd need
to document that it can have undesirable (or at least unpredictable)
effects on existing codes (especially already-compiled codes).

>Although spilling in extended precision would make things somewhat
>more consistent, I don't think it'd be consistent enough to really
>help - it'd still mostly leave the comparison problems.

So would 64-bit-mode FPU, I think, when it comes to 32-bit comparisons.

And, remember, Fortran has "real" 32-bit-FP handling compared to C,
in the sense that the Fortran community has long had reliable
declaration and use of 32-bit FP, something not true for the C
community (which long had to assume 64-bit FP would get used, regardless
of what we declared explicitly or otherwise).

So you can't just hand-wave 32-bit FP processing by saying "well,
most C programmers won't really care if 32-bit FP values are
processed with 64-bit precision", even though you'd probably be right,
because many *Fortran* programmers *would* care.

>It'd also
>still leave the uncertainties of when extended precision gets used
>because the compiler is still free to decide when and how things move
>into registers.

The jury is still out on that, and I feel the problems cannot be
completely addressed (with any adequate performance ratio) either
way.  But I think the numerical community will, at least for a time,
prefer computing and spilling 80-bit values, as a default on machinery
that prefers 80-bit FP computation.

IMO doing 80-bit spills of stuff we already calculate in 80 bits
poses the least risk and least performance drop.

And, the benefit I like most about it, aside from it just making sense
(assuming we don't go to 64-bit-mode FPU, i.e. my "if your registers
are 80-bit, you'd better spill them to 80-bit memories" argument :),
is that, if we do this, we offer the industry a "benchmark" of sorts
to at least thrash out what the *actual* effects of widespread, easily
available, more-predictable 80-bit computing of intermediate results
will be.  This benchmark would be in the form of the gcc compiler
suite.

It might also give some numerical shops more reason to make g77/gcc/g++
their "default" compiler.

>I guess the only problem with:
>
>   __setfpucw ((_FPU_DEFAULT & ~_FPU_EXTENDED) | _FPU_DOUBLE);
>
>really is a portablility issue.  Maybe I'll try it on my code where
>I've had to resort to -ffloat-store and see if it helps.

It should, assuming you're using 64-bit FP pretty much exclusively
(little or no pertinent 32-bit FP).

And the portability issue should not, IMO, be a reason to not do what
you're proposing.  If we decide it'll be better for the numerical
community as a whole to go with 64-bit-mode FPU, then it's really
just a matter of deciding *how* to do it (set it once and for all
in crtN or main()? set it at the beginning of any procedure that
uses FP? re-set it after any call to a "mysterious" procedure? save
it whenever setting, and maybe re-setting, it, to restore it at
any procedure return?) at a design level.

Once we decide that, then I think implementation, albeit hairy,
should not get in our way of making the right decision.

I just don't think this is the right direction, and I'd sure like
to see a lot more hairy numerical types agree with it first before
we spend much more time discussing it, or (especially) talking about
how it just won't bother anyone important if we go ahead and do
it (because I think such talk would be wrong).  (By "hairy" I don't
mean they have to have beards, or be men; they just have to email
as if they did.)

In the meantime, switching to 80-bit spills seems least likely
to hurt anyone, to noticably hurt performance, etc., though I
still don't expect it's an easy thing to do (else I've submitted
a patch by now :).

        tq vm, (burley)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]