Board index » delphi » FP params

FP params


2006-07-01 09:02:18 AM
delphi222
Is there any way to get Delphi to pass FP parameters in FPU regs rather than
passing them on the call stack?
cheers,
chris
 
 

Re:FP params

Hi
Quote
Is there any way to get Delphi to pass FP parameters in FPU regs rather
than
passing them on the call stack?
No ;-(
Best regards
Dennis Kjaer Christensen
 

Re:FP params

"Dennis" <XXXX@XXXXX.COM>writes
Quote
Hi

>Is there any way to get Delphi to pass FP parameters in FPU regs rather
than
>passing them on the call stack?

No ;-(
Thats a shame. :-(
chris
 

Re:FP params

chrisj a écrit :
Quote
Is there any way to get Delphi to pass FP parameters in FPU regs rather than
passing them on the call stack?
No and I'd not recommend that feature.
It could lead to FP stack overflows when a function has too many
arguments or during some recursive calls.
--
Florent Ouchet
 

Re:FP params

Quote
>Is there any way to get Delphi to pass FP parameters in FPU regs
>rather than passing them on the call stack?

No and I'd not recommend that feature.
It could lead to FP stack overflows when a function has too many
arguments or during some recursive calls.
Actually i think Borland should do more work on using the FPU stack
efficiently and securely. Of these identical pieces of code, the former
is much less efficient than the latter because it performs many loads,
stores and waits. The latter uses only the FPU stack for storing values.
(this has actually been reported on QC four years ago and it is still
not opened: qc.borland.com/wc/qcmain.aspx
procedure TForm1.Button1Click(Sender: TObject);
var
X: Extended;
begin
X := Sin(1);
X := X + 1;
X := X * 2;
X := X - 2;
X := X / 2;
if X>0 then; // Avoid warning
end;
procedure TForm1.Button2Click(Sender: TObject);
var
X: Extended;
begin
X := ((Sin(1) + 1) * 2 - 2) / 2;
if X>0 then; // Avoid warning
end;
Note also that the identity calculation is not detected (although
perhaps we shouldn't expect that much cleverness from a compiler) and
that Sin(1) is not considered a constant even though Sin is a compiler
magic function.
It's also interesting to see that the first one is loaded from memory,
not using the special fld1 instruction.
On the other hand, Delphi also doesn't always store stack slots in
memory when needed either. It doesn't keep track of how much of the
stack is used, resulting in an FP stack overflow with the following
code:
procedure TForm1.Button2Click(Sender: TObject);
var
X: Extended;
begin
X := 0;
X := X*X + (X*X + (X*X + (X*X + (X*X + (X*X + (X*X + (X*X + X)))))));
if X>0 then; // Avoid warning
end;
I don't think that the FP part of the Delphi compiler ever got much
attention.
--
The Fastcode Project: www.fastcodeproject.org/
 

Re:FP params

Hi
Quote
I don't think that the FP part of the Delphi compiler ever got much
attention.
I agree. It is a shame. A few small optimizations could improve the compiler
generated code very much.
I do not understand why these reports have been closed. The resolution
comments do not make much sense to me.
FP Code Optimization 1
qc.borland.com/wc/qcmain.aspx
FP Code Optimization 2
qc.borland.com/wc/qcmain.aspx
FP Code Optimization 3
qc.borland.com/wc/qcmain.aspx
FP Code Optimization 5
qc.borland.com/wc/qcmain.aspx
FP Code Optimization 6 - Common Subexpression Elimination
qc.borland.com/wc/qcmain.aspx
FP Code Optimization 7 - Loop Invariant Code Motion
qc.borland.com/wc/qcmain.aspx
Best regards
Dennis Kjaer Christensen
 

Re:FP params

Quote
I do not understand why these reports have been closed. The resolution
comments do not make much sense to me.
It actually may not make sense at all, on the non-tech newsgroup it was
reported that they ran some automated synchronization tool on QC and
some other internal database, and apparently this resulted in massive
closing of QC entries...
Some high-profile ones were reopened after complaints in the newsgroup,
but why they didn't just rollback the whole mess is a mystery.
Best bet would probably to report it, and consider QC as a dead duck
until they fix the poor thing.
Eric
 

Re:FP params

Quote
>I don't think that the FP part of the Delphi compiler ever got much
>attention.

I agree. It is a shame. A few small optimizations could improve the
compiler generated code very much.

I do not understand why these reports have been closed. The resolution
comments do not make much sense to me.
I agree. These reports are complete and relevant; they should never
have been closed like that. I guess Eric's post explains it.
Perhaps there are also QC moderators reading these groups? In this case
they should be able to reopen the reports.
The only other solution i can think of would be to repost each of them,
referring to the original reports.
--
The Fastcode Project: www.fastcodeproject.org/
 

Re:FP params

Avatar Zondertau a écrit :
Quote
Note also that the identity calculation is not detected (although
perhaps we shouldn't expect that much cleverness from a compiler) and
that Sin(1) is not considered a constant even though Sin is a compiler
magic function.
Are the return values of Sin(1) identical depending on the rounding mode
and/or precision flag?
I did a test and it is not constant depending on the rounding mode:
Single Nearest 2170674878A46AD7FE3F
Double Nearest 2170674878A46AD7FE3F
Extended Nearest 2170674878A46AD7FE3F
Single down 2070674878A46AD7FE3F
Double down 2070674878A46AD7FE3F
Extended down 2070674878A46AD7FE3F
Single up 2170674878A46AD7FE3F
Double up 2170674878A46AD7FE3F
Extended up 2170674878A46AD7FE3F
Single zero 2070674878A46AD7FE3F
Double zero 2070674878A46AD7FE3F
Extended zero 2070674878A46AD7FE3F
(raw bytes of the Extended value are printed using the little-endian
convention).
program Project34;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TExtendedRaw = packed record
case Byte of
0 : (ExtendedValue: Extended);
1 : (RawBytes: array [0..9] of Byte);
end;
var
SinusValue: TExtendedRaw;
IndexRound, IndexPrecision, IndexOutput: Integer;
begin
for IndexRound := 0 to 3 do
for IndexPrecision := 0 to 3 do
begin
case IndexPrecision of
0 : Write('Single ');
1 : Continue;
2 : Write('Double ');
3 : Write('Extended ');
end;
case IndexRound of
0 : Write('Nearest ');
1 : Write('down ');
2 : Write('up ');
3 : Write('zero ');
end;
Set8087CW($3F or (IndexPrecision shl 8) or (IndexRound shl 10));
SinusValue.ExtendedValue := Sin(1);
for IndexOutput := 0 to 9 do
Write(IntToHex(SinusValue.RawBytes[IndexOutput], 2));
WriteLn;
end;
ReadLn;
end.
--
Florent Ouchet
 

Re:FP params

Quote
>Note also that the identity calculation is not detected (although
>perhaps we shouldn't expect that much cleverness from a compiler)
>and that Sin(1) is not considered a constant even though Sin is a
>compiler magic function.

Are the return values of Sin(1) identical depending on the rounding
mode and/or precision flag?

I did a test and it is not constant depending on the rounding mode:
Well spotted, but the same thing goes for FP operations that are
simplified by the compiler. I modifed your program to determine the
difference between squaring a const and squaring the same var.
ISTM this leaves Borland two choices: consider compile-time calculation
of multiplication a bug or consider compile-time calculation of the Sin
(and other compiler magic functions) a possible and acceptable
optimization.
My results:
Single Nearest const * const 5A8B7C3AF29A17C3FF3F
var * var 00000000009B17C3FF3F
Double Nearest const * const 5A8B7C3AF29A17C3FF3F
var * var 00887C3AF29A17C3FF3F
Extended Nearest const * const 5A8B7C3AF29A17C3FF3F
var * var 5A8B7C3AF29A17C3FF3F
Single down const * const 5A8B7C3AF29A17C3FF3F
var * var 00000000009A17C3FF3F
Double down const * const 5A8B7C3AF29A17C3FF3F
var * var 00887C3AF29A17C3FF3F
Extended down const * const 5A8B7C3AF29A17C3FF3F
var * var 5A8B7C3AF29A17C3FF3F
Single up const * const 5A8B7C3AF29A17C3FF3F
var * var 00000000009B17C3FF3F
Double up const * const 5A8B7C3AF29A17C3FF3F
var * var 00907C3AF29A17C3FF3F
Extended up const * const 5A8B7C3AF29A17C3FF3F
var * var 5B8B7C3AF29A17C3FF3F
Single zero const * const 5A8B7C3AF29A17C3FF3F
var * var 00000000009A17C3FF3F
Double zero const * const 5A8B7C3AF29A17C3FF3F
var * var 00887C3AF29A17C3FF3F
Extended zero const * const 5A8B7C3AF29A17C3FF3F
var * var 5A8B7C3AF29A17C3FF3F
My program:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TExtendedRaw = packed record
case Byte of
0: (ExtendedValue: Extended);
1: (RawBytes: array[0..9] of Byte);
end;
const
ValueConst = 1.234567890123456789012345;
var
IndexRound, IndexPrecision, IndexOutput: Integer;
MulValue1, MulValue2: TExtendedRaw;
ValueVar: Extended = ValueConst;
begin
for IndexRound := 0 to 3 do
for IndexPrecision := 0 to 3 do
begin
case IndexPrecision of
0 : Write('Single ');
1 : Continue;
2 : Write('Double ');
3 : Write('Extended ');
end;
case IndexRound of
0 : Write('Nearest ');
1 : Write('down ');
2 : Write('up ');
3 : Write('zero ');
end;
Set8087CW($3F or (IndexPrecision shl 8) or (IndexRound shl 10));
MulValue1.ExtendedValue := ValueConst * ValueConst;
MulValue2.ExtendedValue := ValueVar * ValueVar;
Write('const * const ');
for IndexOutput := 0 to 9 do
Write(IntToHex(MulValue1.RawBytes[IndexOutput], 2));
WriteLn;
Write(' var * var ');
for IndexOutput := 0 to 9 do
Write(IntToHex(MulValue2.RawBytes[IndexOutput], 2));
WriteLn;
end;
ReadLn;
end.
--
The Fastcode Project: www.fastcodeproject.org/
 

Re:FP params

"Avatar Zondertau" wrote
Quote
>Are the return values of Sin(1) identical depending on the
>rounding mode and/or precision flag? I did a test and
>it is not constant depending on the rounding mode:
Well spotted, but the same thing goes for FP operations
that are simplified by the compiler.
I think that there is an interesting problem when deciding
whether to pass intermediate or reused FP results on
in the FPU registers or in program variables. Interesting,
in that the movement of the data from the FPU register to
a program variable of lesser precision and back to an
FPU register can cause a extra rounding operation to
occur.
Regards, JohnH
 

Re:FP params

Quote
>>Are the return values of Sin(1) identical depending on the
>>rounding mode and/or precision flag? I did a test and
>>it is not constant depending on the rounding mode:

>Well spotted, but the same thing goes for FP operations
>that are simplified by the compiler.

I think that there is an interesting problem when deciding
whether to pass intermediate or reused FP results on
in the FPU registers or in program variables. Interesting,
in that the movement of the data from the FPU register to
a program variable of lesser precision and back to an
FPU register can cause a extra rounding operation to
occur.
IMO the conclusion by Borland should be: writing code that assumes
floating point math is exact is a bug in itself and there's no hope
that Delphi (or any compiler) can get such code to run such code
reliable. Therefore:
- A warning should be generated for FP tests for equality or inequality
- They need not have reservations against optimizations that may change
the result slightly, since FP math is fundamentally inexact anyways
--
The Fastcode Project: www.fastcodeproject.org/
 

Re:FP params

"Avatar Zondertau" wrote
Quote
IMO the conclusion by Borland should be: writing code that
assumes floating point math is exact is a bug in itself and
there's no hope that Delphi (or any compiler) can get such
code to run such code reliable.
Myself, I find the FPU calculations quite reliable, except when
done by the code of programmers who do not understand
the fundamentals of the way the FPU numbers are stored
and used. I also think that modern programmers have
so much else to worry about, that I'd not expect the
ordinary young programmer to have the time or inclination
to learn about the details of the IEEE-754 FPU number
handling. That is why I have been pushing for the inclusion
of fixed and floating decimal numbers into the PC's repertory.
--JohnH
 

Re:FP params

Hi Eric
Thanks for info. I really hope that somebody take action.
Best regards
Dennis Kjaer Christensen