4

Using the fldcw instruction it's possible to change the precision of the FPU unit to 24 or more bits. However after doing some testing I'm starting to think that very few x87 operations are in fact using that setting.

I haven't tested all operations but on this test machine so far, it looks like only fdiv and fsqrt stop computing at the selected precision, and that all other operations (fadd fsub fmul...) always compute full extended precision.

If that was the case I would expect it to be because those 2 instructions (fdiv and fsqrt) are significantly slower then most other x87 FPU instructions so when lower precision is sufficient it's possible to speed them up, but really, I'm just wondering if this has always been the case or if it's a quirk of the very recent processor used in my test machine.

edit: here's delphi code to show it

program Project1;

uses
  windows,dialogs,sysutils;

{$R *.res}

const
 test_mul:single=1234567890.0987654321;

var
 i:longint;
 s:single absolute i;
 s1,s2,s3:single;

procedure test_24;
asm
 mov word([esp-2]),$103f  // 24bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s1]
end;

procedure test_53;
asm
 mov word([esp-2]),$123f  // 53bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s2]
end;

procedure test_64;
asm
 mov word([esp-2]),$133f  // 64bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s3]
end;

begin
 i:=0;
 repeat
  test_24;
  test_53;
  test_64;

  if (s1<>s2) or (s2<>s3) then begin
   showmessage('Error at step:'+inttostr(i));
   break;
  end;

  inc(i);
 until i=0;
 showmessage('No difference found between precisions');
end.

edit2: false alarm, I was mistaken, I was storing as single instead of extended so couldn't catch the difference, here's a fixed test, thanks to hans passant for catching my mistake:

program Project1;

uses
  windows,dialogs,sysutils;

{$R *.res}

const
 test_mul:single=1234567890.0987654321;

var
 i:longint;
 errors:cardinal;
 s:single absolute i;
 s1,s2,s3:extended;

procedure test_24;
asm
 mov word([esp-2]),$103f  // 24bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s1]
end;

procedure test_53;
asm
 mov word([esp-2]),$123f  // 53bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s2]
end;

procedure test_64;
asm
 mov word([esp-2]),$133f  // 64bit precision, trunc
 fldcw word([esp-2])

 fld [s]
 fmul [test_mul]
 fstp [s3]
end;

begin
 errors:=0;
 i:=0;
 repeat
  test_24;
  test_53;
  test_64;

  if (s1<>s2) or (s2<>s3) then begin
   inc(errors);
  end;

  inc(i);
 until i=0;
 showmessage('Number of differences between precisions: '+inttostr(errors));
end.
TLama
  • 75,147
  • 17
  • 214
  • 392
Marladu
  • 545
  • 5
  • 11
  • Could you give us the means to reproduce this (assembly code, …)? Note that some libraries may “helpfully” reset the floating-point control word for you. – Pascal Cuoq Dec 23 '14 at 17:40
  • Oh i just wrote direct assembler code, no surprise code got in there. I'll edit in some code in 5-10 minutes, I'm finishing typing a different question. – Marladu Dec 23 '14 at 18:20
  • Sure, you can't make an instruction that takes only one cycle on a modern processor any faster. – Hans Passant Dec 23 '14 at 18:37
  • @HansPassant There are issues of double-rounding that would make computing to the full precision counter-productive even if the processor has enough time for that and more in a cycle. – Pascal Cuoq Dec 23 '14 at 18:51
  • The manual (volume 1, chapter 8, just below table 8.2) gives a pretty long list of instructions supposedly affected by the precision bits, including FADD and FMUL. So.. I don't know? – harold Dec 23 '14 at 19:06
  • 3
    Not sure what the code is trying to prove, but if you want to see a difference then you'll have to store the result in a double precision variable. – Hans Passant Dec 23 '14 at 19:07
  • Right aahahaaa sorry my bad, maybe it's a case of user error, let me go test it. – Marladu Dec 23 '14 at 19:31
  • Hans Passant: I'm a very flawed person and when storing extended instead of single the difference appears. Woooooppppss! I'll edit the question with the fixed test that proves that I was wrong but please add an answer that says 'You dumb' and I'll accept it so you get your earned internet power points. Apologies to everyone for the false alarm and thanks for all the comments! – Marladu Dec 23 '14 at 19:39

0 Answers0