-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[LVA] Record store as read of source for reference types. #31131
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
Conversation
f7133a9
to
9c732d1
Compare
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.
I don't understand the intention here. Is this a bug fix?
Are you trying to handle the case where a class reference escapes through a store?
If yes, I would be surprised if this is not handled by escape/alias analysis already.
Maybe you clarify the description/comment.
%2 = alloc_ref [stack] $Foo | ||
|
||
%4 = integer_literal $Builtin.Int64, 0 | ||
%5 = struct $Int (%4 : $Builtin.Int64) |
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 test will not compile on 32-bit architectures, where Int is 32 bit. To fix this, use Int64 instead of plain Int.
@eeckstein yes, precisely. That is the issue this solves. The reproducer/test that I've added fails because of the issue brought up in #31136 but, I suspect given the correct input we could get this to fail on master as well. It is handled by analysis but (AFAICT) analysis never runs on stores/store operands. |
@eeckstein here's another example of the same issue (
The second store isn't counted as a read of |
if (!L.isMustAliasLSLocation(R, AA)) { | ||
// If this is a reference type, then the *live* store counts as an unkown | ||
// read. | ||
if (L.getBase()->getType().isAnyClassReferenceType()) |
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 should be unconditional.
9c732d1
to
d919461
Compare
After processing a store, if the store is alive, stops tracking the source if it's a reference type. In the following case: xx = alloc_ref e = ref_element_addr xx store undef to e yy = alloc_ref h = ref_element_addr yy store xx to h use h The first store will be eliminated because there are no reads of any of the projected aliases (xx). However, that's not true, the (second) store counts as a read. If this were a struct, the current assumption would be correct because we couldn't GEP a non-address struct (so there is no way that the source of a store could have a GEP on it). But, reference types do allow GEPs so, this is not a safe assumption.
d919461
to
5630e54
Compare
bb0(%0 : $B): | ||
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B> | ||
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0 | ||
store %0 to %1a : $*B |
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 lose this optimization when the source is a reference type. I think that's a rare case but, I would like to add this back as a special-case optimization in another patch.
This is the wrong approach. A I'm not sure if there is really a bug currently. The SIL in your example is invalid, because it lets the address of a stack location escape after the dealloc_stack |
@eeckstein you're right. This is not the correct fix; it's not a read. I'll close this PR but, I think the issue is actually valid. What's escaping (in the most recent example) is a pointer to type This is a very contrived example but, it shows a technically incorrect behavior. If something like #31136 lands, the problem will become much more common.
|
After processing a store, if the store is alive, stops tracking the source if it's a reference type.
In the following case:
The first store will be eliminated because there are no reads of any of the projected aliases (xx). However, that's not true, the (second) store counts as a read. If this were a struct, the current assumption would be correct because we couldn't GEP a non-address struct (so there is no way that the source of a store could have a GEP on it). But, reference types do allow GEPs so, this is not a safe assumption.