-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[R2R] add a virtualStubParamInfo as an argument #15910
Conversation
@dotnet-bot test Windows_NT arm Cross Checked r2r Build and Test |
@dotnet-bot test Windows_NT arm Cross Checked r2r_jitstress1 Build and Test |
arm r2r testing results:
were fixed.
continue to fail. |
Some strange things about this morphing:
where 'addr' is result of VM call, can we move it to morph? Looks like it is the same additional non-standard argument. |
e6c24a0
to
85742c2
Compare
@dotnet-bot test Windows_NT arm Cross Checked r2r Build and Test |
I need to add a function header and collect SPMI diffs, but we can start review. |
There are many asm diffs for amd64, they will degrade our performance, but they are correct.
after
so out jit can't fold it. Does anybody know how to fix that, @AndyAyersMS? I will try to use lclVar, but expect that it won't help. |
Not really my area of expertise, but if everyone else is tied up I will try and take a look. It's not clear to me from the description above or the linked issue what the problem is and how you are attempting to solve it -- can you say a bit more about this? |
So when we have virtual stub-dispatch calls we have a special calling convention, that says where we pass the address of the stub (doc). This special calling convention was not reflected in the jit properly, in some cases we did not add this special argument to the call. So my change:
but because I changed our trees from:
to
jit now generates additional move to load and we have
the question is how to force jit to load them to the same register and delete this extra move? In other words how to get SSA value in our SDSU model. |
Probably I'm missing something but can't we simply keep the original tree and just require LSRA to assign |
It is how iit was before, but then how can you guarantee that |
Would it be possible to mark the control expression and its indirection both contained for this case? Then the stubAddr is used by the call, and if it is marked as its src requiring it to be in r11, that register will be reserved at the call, even if stubAddr somehow doesn't get r11, or it gets spilled. |
As far as I can tell before the lowering code is simply pulling |
It won't work, because this instructions chain is not a atomic instr. The control expression generates real instruction and can't be marked as contained. I think there is an assert that prevents is:
|
I tried to use lclVars and it did not help, because the jit replaces lclVar with constant. |
What's this real instruction that it generates? For typical VSD calls I see that control expr is a contained indir:
I can't find such an assert. There's the opposite - |
@mikedn This assert is from armarch: coreclr/src/jit/codegenarmarch.cpp Line 2366 in 59714b6
|
Right, I was only looking at x64 code. Of course, it's not contained on ARM because there's nothing like x64's But maybe it's possible to emulate memory operand "containedness" on ARM? Make the indir contained, request an internal register for the call node and emit the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to trigger some armlb R2R testing
@@ -3081,38 +3081,27 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) | |||
|
|||
nonStandardArgs.Add(cns, REG_PINVOKE_COOKIE_PARAM); | |||
} | |||
else if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT) && !call->IsTailCallViaHelper()) | |||
else if (call->IsVirtualStub()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to remove the check for CT_INDIRECT? So the non-CT_INDIRECT calls will also get a non-standard arg?
If so, couldn't you just keep the condition else if (call->IsVirtualStub() && !call->IsTailCallViaHelper())
to avoid nesting the if
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it was one of the problems, CT_DIRECT
also needs this special argument.
If I merge nested if
s, then I won't have place for comment about 'call->IsTailCallViaHelper()` that I think is useful.
@@ -3081,38 +3081,27 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) | |||
|
|||
nonStandardArgs.Add(cns, REG_PINVOKE_COOKIE_PARAM); | |||
} | |||
else if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT) && !call->IsTailCallViaHelper()) | |||
else if (call->IsVirtualStub()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are all these changes going to work with the code generator for LEGACY_BACKEND
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I am not sure that we can test it in ci.
src/jit/morph.cpp
Outdated
@@ -8072,6 +8051,25 @@ void Compiler::fgMorphTailCall(GenTreeCall* call) | |||
DISPTREE(call); | |||
} | |||
|
|||
GenTree* Compiler::fgGetStubAddrArg(GenTreeCall* call) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function needs a header comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
} | ||
else | ||
{ | ||
assert(call->gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did we handle this case before? Or was that the bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, it looks like this was extracted from the amd64 version of fgMorphTailCall(). But it's not the same logic as was previously in fgMorphArgs (now calling this). Is that ok/good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the bug was in unimplemented case for CT_DIRECT
.
Also the was a workaround in lower.cpp
for legacy arm, that did not work write with non-legacy.
#endif | ||
indir->gtFlags |= GTF_IND_REQ_ADDR_IN_REG; | ||
#endif | ||
result = indir; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOVE seeing all this get deleted!
src/jit/morph.cpp
Outdated
GenTree* stubAddrArg = fgGetStubAddrArg(call); | ||
// And push the stub address onto the list of arguments | ||
call->gtCallArgs = gtNewListNode(stubAddrArg, call->gtCallArgs); | ||
#else // !LEGACY_BACKEND |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is backwards: remove the !
. Better, put the LEGACY_BACKEND
case first, to avoid double negative logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
src/jit/morph.cpp
Outdated
|
||
#ifndef LEGACY_BACKEND | ||
GenTree* stubAddrArg = fgGetStubAddrArg(call); | ||
// And push the stub address onto the list of arguments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't you change stubAddrArg
to just arg
and then tail merge the next two lines of this #if
with the same two lines of the #endif
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will delete the legacy soon, so I think it is better to keep this change that way (do not want to move GenTree* stubAddrArg
out of ifdef
or do call->gtCallArgs = gtNewListNode(stubAddrArg, call->gtCallArgs);
that uses stubAddrArg
that is defined twice (under different #ifdefs
).
So the failing tests are failing because of the same issue with incorrect liveness information for |
@dotnet-bot test Windows_NT arm Cross Checked r2r Build and Test |
@BruceForstall, Do we have armlb r2r jobs in ci? I have not found them. PR was updated. Please take another look. |
@dotnet/jit-contrib ping. |
This looks reasonable to me - but just to make sure I understand: this latest round of changes still cause the stub address to be loaded into two registers, right? Would it make sense to file an issue to eliminate that duplication? |
Yes, you are right. The issue was filed (#16037). It shows a general problem with out constant values, because the issue existed before this PR. |
@sandreenko - thanks! I think it would be good to get sign-off from Bruce as well, but this LGTM. |
expect many failures for arm in lower because we delete: // Change the call type, so we can add the extra indirection here, rather than in codegen
f500454
to
fb40204
Compare
@dotnet-bot test Windows_NT arm Cross Checked r2r Build and Test |
So let's see if I understand this correctly. On x64 we'll generate worse code than before due to a problem that seems to be ARM specific and we hope that code gen may improve sometime in the future, if ever. |
The worse code generation is not ARM specific. If you want I can create amd64 example. I do not know a better way how to fix liveness problem without this CQ regression. Different contained hacks do not change liveness and do not fix the real issue here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks Good
For something like this I would have liked to have seen jit diffs results and may be some kind of performance impact assessment. Given our current policy of distributing framework code as R2R's assemblies we need to pay attention to R2R perf. It sounds like what we ended up with is a bit of a compromise and in such cases it is good to get an idea of what we are paying for getting this bug fixed. As things stand it is hard to know if this change is something we can live with or whether we should go back and try and root out what is preventing us from getting to the code we'd like to emit. |
@AndyAyersMS - excellent points.
At a minimum, we should file an issue, with pointers to impacted test cases, so that we can investigate the options. |
@sandreenko Please add diffs and perf analysis. |
We really need to implement CI-triggered all-plat asm diffs, as well as all-plat always-available SuperPMI collections that enable SuperPMI asm diffs. |
Revert #15910 [R2R] add a virtualStubParamInfo as an argument
* add a virtualStubParamInfo as an argument * Revert legacy workaround from lower. Commit migrated from dotnet/coreclr@c4943e0
…gument Commit migrated from dotnet/coreclr@3d510b0
Revert dotnet/coreclr#15910 [R2R] add a virtualStubParamInfo as an argument Commit migrated from dotnet/coreclr@1733bdd
This PR fixes part of #15150 and #15552.