Skip to content

Fix issue 20089: Handle extra case in fixresult_complex87#10247

Merged
thewilsonator merged 3 commits intodlang:masterfrom
marler8997:8087stack
Aug 21, 2019
Merged

Fix issue 20089: Handle extra case in fixresult_complex87#10247
thewilsonator merged 3 commits intodlang:masterfrom
marler8997:8087stack

Conversation

@marler8997
Copy link
Contributor

@marler8997 marler8997 commented Jul 30, 2019

Fix issue 20089, FPU stack not cleaned up properly

Note that this only occurs on windows 64-bit. It doesn't happen on windows 32 bit because it only occurs when the compiler tries to fit a cfloat into the RCX register. With help from @rainers, we added a new if block to handle the case when a cfloat needs to be copied to the one of the R*X register.

@dlang-bot
Copy link
Contributor

dlang-bot commented Jul 30, 2019

Thanks for your pull request and interest in making D better, @marler8997! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
20089 major FPU stack not cleaned up properly

⚠️⚠️⚠️ Warnings ⚠️⚠️⚠️

To target stable perform these two steps:

  1. Rebase your branch to upstream/stable:
git rebase --onto upstream/stable upstream/master
  1. Change the base branch of your PR to stable

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "master + dmd#10247"

@marler8997 marler8997 changed the title Save all values in the 8087 stack Handle extra case in fixresult_complex87 Jul 31, 2019
@marler8997 marler8997 force-pushed the 8087stack branch 2 times, most recently from e65cc31 to f5b2800 Compare July 31, 2019 05:37
@rainers
Copy link
Member

rainers commented Jul 31, 2019

I recently noticed this too: https://issues.dlang.org/show_bug.cgi?id=20089
I think the test would also fail an assertion with non-zero inputs.

pop87();
cdb.genfltreg(ESC(MFfloat,1),BX,0); // FSTP floatreg
genfwait(cdb);
cdb.genfltreg(LOD, CX, 0); // MOV EAX,floatreg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that cfloat is considered a struct, so it is passed in integer registers. But it fits into RCX, so I'd expect that one of the floats has to be packed into the upper half.
BTW: the comments show other registers.

Copy link
Contributor Author

@marler8997 marler8997 Jul 31, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's kinda what I gathered from the code. However, I don't really understand exactly how this code works or how to move the value into the upper part of the register.

Based on the function comment, we need to generate code to move the value from retregs to *pretregs. In this case, retregs is in ST01, but I'm not sure what ST01 means. From wikipedia It looks like there are 8 stack registers (ST1 - ST7) but what is ST01? And I don't see where in this code block the ST01 register is being referenced. I just wrote this code block based on one of the other cases that is moving the value from ST01. I see the comment floatreg so maybe that's what ST01 is?

In any case, this appears to fix test18772 (or at least workaround it), I even added some values in test18772.d to make sure the real part of the float still works. However, I'm using small values so the upper part may be getting lost.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From wikipedia It looks like there are 8 stack registers (ST1 - ST7) but what is ST01?

There are registers ST0-ST7, where ST0 is the one on top of the stack, ST1 is the one below, and so on. mST01 is probably the pair of ST0 and ST1 used for complex numbers.

@marler8997 marler8997 force-pushed the 8087stack branch 3 times, most recently from 6aeea9f to 4b28d85 Compare July 31, 2019 16:13
@marler8997 marler8997 changed the title Handle extra case in fixresult_complex87 Fix issue 20089: Handle extra case in fixresult_complex87 Jul 31, 2019
@marler8997 marler8997 force-pushed the 8087stack branch 3 times, most recently from 2fa2686 to 2dd6ffe Compare July 31, 2019 20:06
@marler8997
Copy link
Contributor Author

marler8997 commented Jul 31, 2019

The PR as is fixes the test, though, the solution is not fully implemented. The commented line I included in the test will pass once the full solution is implemented.

I would be fine with integrating this partial solution as is and let someone more familiar with x86_64 assembly and DMD code generation to finish the solution.

The last part is that the imaginary part of the complex number is getting zero'd in the second MOV instruction to ECX. The first MOV instruction moves the imaginary part to ECX, then I shifted it left by 32 bits, but then the second mov to the lower 32 bits also sets the upper 32 bits to 0. Not sure the best way to solve this one. But since this fixes the test, the PR as is unblocks the PR that moves the build to D and I assume is re-enabling the asserts.

@rainers
Copy link
Member

rainers commented Jul 31, 2019

The last part is that the imaginary part of the complex number is getting zero'd in the second MOV instruction to ECX. The first MOV instruction moves the imaginary part to ECX, then I shifted it left by 32 bits, but then the second mov to the lower 32 bits also sets the upper 32 bits to 0. Not sure the best way to solve this one.

Yes, mov ECX,... clears the upper 32 bits of RCX. You have to move the float to another register, then or both together.

@rainers
Copy link
Member

rainers commented Jul 31, 2019

I would be fine with integrating this partial solution as is and let someone more familiar with x86_64 assembly and DMD code generation to finish the solution.

Maybe it might be better to disable the test until a general fix is found (your patch is a good starting point). I did so in #10231 not expecting a solution soon.

@marler8997
Copy link
Contributor Author

marler8997 commented Jul 31, 2019

Yes, mov ECX,... clears the upper 32 bits of RCX. You have to move the float to another register, then or both together.

That was what I tried next but I couldn't figure out how to generate an OR instruction that worked with the 64-bit registers. The codegen api is pretty difficult to figure out.

@rainers
Copy link
Member

rainers commented Aug 1, 2019

@marler8997 I pushed a version to your branch that should fix the imaginary part (instead of or-ing the results, it just places the two values to consecutive memory locations). It also covers other register targets.
In other situations XMM registers are used instead, but that seems to be broken, too.

@marler8997
Copy link
Contributor Author

@rainers very nice, thanks alot for doing this!

@rainers
Copy link
Member

rainers commented Aug 2, 2019

I've added a fix for the failing test case, but I'm not so confident this time.

@wilzbach wilzbach added the Review:Blocking Other Work review and pulling should be a priority label Aug 11, 2019
@thewilsonator
Copy link
Contributor

Ping, this good to go?

@marler8997
Copy link
Contributor Author

I've fixed the merge conflicts, I would say it's ready, we'll see what @rainers says.

@rainers
Copy link
Member

rainers commented Aug 20, 2019

Fine with me.

@thewilsonator thewilsonator merged commit aa94684 into dlang:master Aug 21, 2019
@marler8997 marler8997 deleted the 8087stack branch August 21, 2019 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review:Blocking Other Work review and pulling should be a priority Severity:Bug Fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants