-
Notifications
You must be signed in to change notification settings - Fork 5.3k
JIT: Expand recognition of struct field offset pattern #122297
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
JIT: Expand recognition of struct field offset pattern #122297
Conversation
The JIT has an optimization to recognize recomputations of field
offsets, but this optimization failed to trigger in certain cases when
the struct was promoted with old promotion.
```csharp
public unsafe nint Test()
{
MyStruct dummy;
return (nint)((byte*)&dummy.Field - (byte*)&dummy);
}
```
Before:
```asm
G_M27992_IG01: ;; offset=0x0000
push rax
xor eax, eax
mov qword ptr [rsp], rax
;; size=7 bbWeight=1 PerfScore 2.25
G_M27992_IG02: ;; offset=0x0007
lea rax, [rsp+0x04]
lea rcx, [rsp]
sub rax, rcx
;; size=12 bbWeight=1 PerfScore 1.25
G_M27992_IG03: ;; offset=0x0013
add rsp, 8
ret
;; size=5 bbWeight=1 PerfScore 1.25
```
After:
```asm
G_M27992_IG02: ;; offset=0x0000
mov eax, 4
;; size=5 bbWeight=1 PerfScore 0.25
G_M27992_IG03: ;; offset=0x0005
ret
;; size=1 bbWeight=1 PerfScore 1.00
```
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
|
PTAL @dotnet/jit-contrib |
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.
Pull request overview
This PR enhances the JIT compiler's optimization to recognize and fold struct field offset computations when structs are promoted using old promotion. Previously, the optimization only worked when computing offsets between the same local variable, but failed when promoted struct fields were involved.
- Extends the SUB node optimization to resolve parent local variables and aggregate field offsets for promoted struct fields
- Enables compile-time constant folding of field offset patterns that previously required runtime computation
- Significantly improves code generation by eliminating unnecessary address arithmetic
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.
Just so that I understand here: this opt wasn't getting applied to some struct fields which were promoted to locals because they would each have their own local numbers. However, in these cases, the locals should share a parent local, so we can change the condition to be whether the parent local matches to ensure that the two locals are part of the same struct?
Yes, that's pretty much it. When a promoted struct has its address taken (either the struct local itself or any of its fields) then the storage of the struct local and all its fields will be shared. This is called dependent promotion. It is a bit unusual -- in those cases we cannot enregister the struct fields, and we would usually have preferred not to promote at all. But we don't know whether the address is taken until after promotion today. In this particular case since we know the address is taken we know that the field would end up sharing its storage with the parent. And hence we can still compute the address statically. Note that we are working towards removing this promotion mechanism (which we usually call "old" promotion) in favor of a new promotion mechanism called "physical promotion". Physical promotion does not have a concept of dependent promotion or shared storage, fields always get their own completely independent locals. |
|
Ping @dotnet/jit-contrib, need an approval here. |
adamperlin
left a 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.
This looks good to me from what I understand!
|
Thank you for the detailed explanation here. I was wondering what was meant by "old" vs. "new" promotion! |
The JIT has an optimization to recognize recomputations of field offsets, but this optimization failed to trigger in certain cases when the struct was promoted with old promotion.
Before:
After: