-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First Class Structs: stop lying about underlying type. #1231
Comments
I think the first approach (teach rationalize how to deal with struct ASG trees) is the right one. Are there advantages to doing the second? I know that eventually we want to import assignments as stores, but I guess I don't understand the complexity of handling struct assignments in rationalizer. |
Great!
Presumably you mean
Currently I'm working on
That's tempting. But it may turn out to be a large amount of work, relative to the problem you're trying to solve. Nothing in the frontend understands these stores so you'll very likely need to patch up at least morph, assertion prop, SSA and VN. Granted, in the specific case of a call as RHS things should be simpler:
I'm still not sure what exact problem you have found in rationalization. There's this bit of code: runtime/src/coreclr/src/jit/rationalize.cpp Lines 356 to 397 in c4f221c
ASG . If codegen does not support struct typed STORE_LCL_VAR it's lowering's job to convert these to STORE_OBJ .In any case, this rationalization code already ignores ASG s with a "multi reg call" as RHS so presumably you can easily extend this to "any reg call".
|
I happen to have a little change I've done a while ago that may be of some help. It's not related to calls but it tries to make It only handles the |
The current way of representation of struct
we add conservative runtime/src/coreclr/src/jit/simd.cpp Lines 3199 to 3207 in 890b890
and it affects the later phases, probably, that can be fixed directly by deleting that setting as the comment says, but I think these nodes have negative impact on other phases before rationalize (like |
The conservative handling of struct copies is something that needs to change. Some of these pessimizations were removed, only to be re-added later as an expedient, rather than fixing CSE. I'm not certain that's the case in this instance, but I think we should pursue this avenue. |
I have checked my notes and found that asserts were not in the rationalization phase, sorry for the confusion. But rationalize was transforming
IR without fixup after importation (new):
after rationalize:
IR with fixup after importation (old):
after rationalize:
Is |
Yes, because copy/init block codegen does not support struct typed
IMO yes, it should be |
Agreed; we want to move toward using a simple |
Thanks, that was a very helpful discussion for me. I will stop doing changes before rationalizing (except deletion of retyping), adopt @mikedn's change and come back with results. |
a small update, I was able to compile and run
dumps are attached, the difference that pri0 test results:
the changes are in that branch (but it is not ready for review). The are many problems, the main are:
then there is interaction with
and then we end up with
so we have
|
This looks like great progress!
I think the right answer is to delay the introduction of the bitcast to I've made some additional changes to my SIMD8 PR (#811) mostly to improve performance. I haven't done much testing on it at this stage, so it may actually be worse than before correctness-wise. |
a small update from the offline discussion with Carol: It creates many interesting cases, for example,
we are importing:
and then was retyped as:
and after lowering it looked like:
in the new version:
that we don't know how to generate (no struct handle), so temporary I block such assertion propagation but it looks like we are missing an optimization opportunity here. |
FWIW using |
Agreed. This was something that was actual made worse by the first round of first class structs changes and I debated but decided not to add the extra node where "not needed" (though I've come to believe that it is, in fact, needed).
That seems like a promising idea; I presume that it would have store semantics, and look a lot like |
Not really. I think that IL's C# code: Foo(new BarStruct()); IL code:
ASM code:
While it's possible to improve the JIT to handle this better, things would have been easier if the IL was just:
That's |
INIT_VAL right now doesn't have However, from what I saw, As I understand the proposed design is to create a new node for
nowadays we generate I like the idea, especially because it can be done in the master branch as a separate PR. |
Yes, it's probably easy to add layout to it but it's not very useful ATM because
Yes, that's pretty much why it exists. I think that the more precise reason is that without it the IR semantics might be a bit ambiguous - is
Perhaps, I'm not sure how common
I think that the main problem with adding something like As for the main advantage - this is IMO pushing the JIR IR in the right direction by removing a case of context dependent node semantics. From
Well, it should avoid the issue you're having with Maybe it could also be used to improve the codegen in the example I posted above but I haven't checked what's going on there. That's probably a rather different issue (e.g. it could be that because the temporary created for implicit byref args is address exposed assertion propagation doesn't touch it even though it could in this case). |
I am trying to get rid of some pessimizations following first-class-structs design, cc @CarolEidt.
The main performance issue is struct returns that are wrapped as int or long types. In these cases even if we inline these calls we can't promote/enregister structs or their fields.
To stop retyping we need to stop calling
impFixupCallStructReturn
andfgFixupStructReturn
, like this.but then you will get errors in rationalize because it doesn't expect
ASG struct
trees.I see two possible solutions:
STORE_LCL/BLK/OBJ
in importer, like ingtNewBlkOpNode
gentree.cpp.the second interferes with the work of deleting
ASG
from @mikedn, so that issue is created to discuss how we can make progress without creating merge conflicts. @mikedn how do you seeASG
nodes replacement, are you planning to delete it completely, including importation phase?An example how we keep struct type with the second approach
1. System.IO.FileSystem:FillAttributeInfo(System.String,byref,bool):int (MethodHash=333db0b0) (from VectorAdd_r.dll)for such IL:
the old generates:
then transforms it to:
and then generates:
mov qword ptr [V04 rbp-290H], rax
the new importer:
then:
then:
mov qword ptr [V04 rbp-29CH], rax
so we can keep
STRUCT
type and with changes in lowering can enregister them.Other examples.
2. from VectorAddTest`1[Single][System.Single]:VectorAdd(float,float,float):int (MethodHash=051d27ab) (from VectorAdd_r.dll)for such IL:
the old importer generates:
then rationalize changes it to:
and the final result is:
the new importer generates:
and doesn't do any tranformations later.
in order to keep STORE_LCL_VAR add DA flags.
for such IL:
the old importer:
then
the new importer generates:
IL:
old import:
after rationalize:
new import:
category:cq
theme:structs
skill-level:expert
cost:large
The text was updated successfully, but these errors were encountered: