Recent

Author Topic: Strange Floating Point XMM Errors on WIN64  (Read 3079 times)

schuler

  • Full Member
  • ***
  • Posts: 103
Strange Floating Point XMM Errors on WIN64
« on: October 13, 2017, 09:07:17 am »
 :) Hello Pascal Lovers  :)

I'm not sure if I'm typing here with the goal to save time to others in the case that they get the same error as I got or if I want to know if I found a bug. Anyway, here we go.

I have 3 functions: A, B and C. Function A calls B. B calls C. C contains both pascal and asm code.

Function A shows strange floating point errors including division by zero error.

This is a portion of function C:

Code: Pascal  [Select]
  1.   asm
  2.   ...
  3.   vmovups ymm6, [rax+64]
  4.   ...
  5.     end
  6.   [
  7.     'RAX',
  8.     'XMM6',
  9.     'ymm6'
  10.   ];
  11.  

After 4 or 5 hours debugging, I found that a floating point value stored on XMM6 on function A was being lost. Then, I found this link:

http://wiki.lazarus.freepascal.org/Win64/AMD64_API

From above link, I can read:
Quote
other nonvolatile registers, if used, should be pushed on stack. These registers are R12 through R15, RDI, RSI, RBX, XMM6 through XMM15

I though that signaling usage of either XMM6 or YMM6 would solve the problem:
https://www.freepascal.org/docs-html/prog/progse12.html#x149-1500003.4

But I think that this is not the case. Not sure if this is a bug or not. If I were coding the compiler, I would not to be sure although I'm tempted to look at how the signaling was implemented.

HOW TO SOLVE
This is how I solved in my case:

Code: Pascal  [Select]
  1. var
  2.   mxmm6: array[0..3] of Single;
  3. begin
  4.   ...
  5.   asm
  6.   movups mxmm6, xmm6  // saves xmm6
  7.   ...
  8.   movups xmm6, mxmm6 // restores xmm6 - YAY!!!
  9.   end ['RAX'];
  10.  

So far, this problem shows up on Windows 64 only. Linux 64 with same code works well so far.

Please feel free to comment.

:) wish everyone happy coding :)

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7252
Re: Strange Floating Point XMM Errors on WIN64
« Reply #1 on: October 13, 2017, 10:01:48 am »
Some tips:

Please try to make a small demo that demonstrates the problem, that we can compile with -a on various branches. Fragments can be useful if sb directly sees the problem, but this probably requires further investigation

ABI only knows and saves XMM registers, the upper part of YMM is always considered lost.

If you use YMM you are supposed to run a vzeroupper afterwards, though afaik that is only a performance optimization.

schuler

  • Full Member
  • ***
  • Posts: 103
Re: Strange Floating Point XMM Errors on WIN64
« Reply #2 on: October 15, 2017, 08:06:25 am »
Hello Marcov,
I'll try to create a small demo and post here.

Thank you for your help.

schuler

  • Full Member
  • ***
  • Posts: 103
Re: Strange Floating Point XMM Errors on WIN64
« Reply #3 on: October 25, 2017, 02:07:06 am »
MARCOV!!!

Just been able to reproduce with:
Code: Pascal  [Select]
  1. procedure TestC(); inline;
  2. begin
  3.   asm
  4.     vxorps xmm6, xmm6, xmm6
  5.   end ['XMM6','YMM6'];
  6. end;
  7.  
  8. procedure TestA();
  9. var
  10.   S1: Single;
  11. begin
  12.   S1 := 1;
  13.  
  14.   TestC();
  15.  
  16.   WriteLn(S1:4:2);
  17. end;
  18.  

If you call TestA above, you'll see that 1 is loaded into xmm6. Then, xmm6 is zeroed by TestC.

Should I log a bug report?

 :) Wish everyone happy coding :)

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7252
Re: Strange Floating Point XMM Errors on WIN64
« Reply #4 on: November 05, 2017, 04:41:00 am »
I can't quickly reproduce since my local build seems corrupt (keeps saying can't find identifier XMM6).

I think having both xmm6 and ymm6 in the save register list is wrong (should be only ymm6), and probably never inlinable.

But yes, file a bug even if only for better errrorgeneration

schuler

  • Full Member
  • ***
  • Posts: 103
Re: Strange Floating Point XMM Errors on WIN64
« Reply #5 on: June 21, 2019, 02:42:11 pm »
:) Hi :),
Almost 2 years later, came across to the same problem. Today, it happened to me on WIN64 with release settings (no debug info).

I'm wondering: can anyone try to reproduce this problem please?

julkas

  • Full Member
  • ***
  • Posts: 175
  • KISS principle
Re: Strange Floating Point XMM Errors on WIN64
« Reply #6 on: June 21, 2019, 03:29:17 pm »
I'm wondering: can anyone try to reproduce this problem please?
Running your code example in DEBUG mode, result - 1.00. RELEASE - 0.00
Lazarus 2.0.0 / FPC 3.0.4
----------------------------
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7252
Re: Strange Floating Point XMM Errors on WIN64
« Reply #7 on: June 21, 2019, 04:29:33 pm »
I compiled it with trunk and yes. xmm6 is callee saved, as per ABI. That is what putting the register name it in end[] does.

If you don't put it there, it is fine, but since xmm6 is chosen by the compiler as location for "s1", this is extremely dodgy code.

schuler

  • Full Member
  • ***
  • Posts: 103
Re: Strange Floating Point XMM Errors on WIN64
« Reply #8 on: June 21, 2019, 05:11:05 pm »
@julkas and marcov,
Thank you for your super quick replies! :)

From what you've both replied, I can conclude that we do have a problem on FPC 3.0.4 that has already been fixed on trunk. This is good news.

:) Wish everyone happy pascal coding :)