Implement integer to long/ulong casts for x86#4986
Conversation
|
@BruceForstall In addition to the sign extension issue I also added support for casts with overflow checks, initially I wasn't sure how well it will work but it seems easy enough. |
| hiStore->gtOp.gtOp1 = hiRhs; | ||
| hiStore->CopyCosts(tree); | ||
| hiStore->gtFlags |= GTF_VAR_DEF; | ||
| hiStore->gtFlags = tree->gtFlags; |
There was a problem hiding this comment.
I'm not sure this is the proper fix. The issue is that the hiStore tree lacks the GTF_EXCEPT flag that overflow checks add and an assert fires. Simply copying all flags appears to work fine.
There was a problem hiding this comment.
I think that the right fix is hiStore->gtFlags |= (tree->gtFlags & (GTF_ALL_EFFECT|GTF_LIVENESS_MASK));
|
Looks like you have a few relevant test failures in the x86 ryujit suite. |
|
I'll look (might be tomorrow). Also, @adiaaida PTAL |
| { | ||
| comp->fgInsertEmbeddedFormTemp(&tree->gtOp.gtOp1); | ||
|
|
||
| loResult = tree->gtGetOp1(); |
There was a problem hiding this comment.
Why aren't we using srcOp here?
There was a problem hiding this comment.
@adiaaida fgInsertEmbeddedFormTemp replaces the operand, probably I should add a srcOp = tree->gtGetOp1() right after fgInsertEmbeddedFormTemp for clarity. Or just get rid of srcOp completely.
|
The assert that fires in test JIT\Regression\JitBlue\DevDiv_200492\DevDiv_200492\DevDiv_200492.cmd is interesting. The generated code looks like: I doubt that it's valid to throw when |
|
Test JIT\Methodical\fp\exgen\10w5d_cs_do\10w5d_cs_do.cmd is a nightmare. It fails left and right depending on options such as JitInline and JitMinOpts. For example, if I use JitMinOpts=1 I get some code like the following: This might have something to do with float/double returns but I don't know what this has to do with my cast changes. The method where this happens doesn't even use long operations. |
|
Well, RyuJIT x86 is pretty raw... Try using |
|
For now I created #5047 to deal with the bad float return issue. I'll have to double check but the nightmare test seems to pass if that issue is fixed. |
|
Found another issue with long operations while investigating JIT\Methodical\fp\exgen\10w5d_cs_do\10w5d_cs_do.cmd. Sometimes lowering replaces an |
|
Tests pass if workarounds are added for the 3 unrelated bugs I've found. However, this implementation is still flawed, the following test asserts: Test is adapted from the test I made for the div/mod assert so the problem is likely similar - using |
|
Turns out that the above issue is caused by a bug in How do we move forward with all this stuff? Attempting to add support for long casts uncovered 4 unrelated issues. Probably the same thing will happen if we try to add support for other long operations. |
| } | ||
|
|
||
| frameType = FT_EBP_FRAME; | ||
|
|
There was a problem hiding this comment.
Why is this unconditionally setting the frame type to EBP?
There was a problem hiding this comment.
Temporary workaround to get JIT\Regression\JitBlue\DevDiv_200492\DevDiv_200492\DevDiv_200492.cmd working, see explanation a few posts above. The correct solution is to detect when an EBP frame is required for x86. Probably I should create an issue for this.
Obviously, those workarounds need to be removed if this is to be merged.
|
@mikedn - Given where we are with supporting longs on 32-bit, I think that the only near-term way forward is to deal with each of these issues in turn; I wish I could give a more definitive answer, but I think some of what we are doing is postulating a way forward, and then discovering the issues. |
I suppose separate issues should be created and addressed individually rather than attempting to fix everything in a single PR?
Might be easier to always put the hiStore in an embedded statement before the loStore, even if this means that those stores don't follow the usual lo/hi order. Anyway I'm not sure how the current code works at all, it would seem that dragging hiRhs in a separate statement would cause a lot of problems if hiRhs is not a leaf.
Or adding a |
Or perhaps we can piggyback on the existing but presently unused |
|
I hadn't realized that
That would be great. Without your changes, can you duplicate the |
See #5696 |
cfeb403 to
2be4617
Compare
| // original store's side effecs to both parts. | ||
| unsigned flags = tree->gtFlags & ~GTF_ALL_EFFECT; | ||
| unsigned loFlags = flags | (loRhs->gtFlags & GTF_ALL_EFFECT); | ||
| unsigned hiFlags = flags | (hiRhs->gtFlags & GTF_ALL_EFFECT); |
There was a problem hiding this comment.
The store nodes should also have the GTF_ASG flag set. We should probably validate that all stores have this flag set in CheckLIR, but that change should be made separately.
|
I think this is very close: the changes at https://gist.github.com/pgavlin/77e2364408d6e63223b19319757c2170 take care of the cost-related asserts. |
3662f2f to
f19aac6
Compare
|
@mikedn: the cost changes should no longer be necessary, no. If you notice any parts of the backend that still attempt to maintain cost info, those parts should be fixed. |
|
(indeed, attempting to maintain cost information may even cause asserts if the source node was added or modified by rationalize, which no longer sets or maintains cost info) |
d7f141c to
ac14e3c
Compare
|
The failure of |
609ea38 to
9c3c556
Compare
|
Well, this one is ready provided that we decide what to do about the failing test. It may sound odd but I'd fix the test because that long comparison is probably an accident. #7038 contains a much simpler repro that we can later add as a separate test. |
| case TYP_INT: | ||
| if (tree->gtFlags & GTF_UNSIGNED) | ||
| if (varTypeIsUnsigned(srcType)) | ||
| { |
There was a problem hiding this comment.
Nit: might be nice to have a note in here that this is a conversion (u32 -> u64) that cannot overflow.
|
LGTM aside from a couple nits re: comments. |
9c3c556 to
30803e0
Compare
|
@mikedn Nice! Thanks for the work! |
Implement integer to long/ulong casts for x86 Commit migrated from dotnet/coreclr@a04c2e3
Implement various integer to long/ulong casts for x86. Sign extension is performed using an arithmetic shift to avoid the need for the x86 specific
cdq. Overflow checks are implemented by using int->uint casts for which codegen provides the necessary overflow support.Fixes #4664, #4174, #4175