-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SILOptimizer] Add RedundantMoveValueElimination. #64190
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
[SILOptimizer] Add RedundantMoveValueElimination. #64190
Conversation
@swift-ci please test |
@swift-ci please benchmark |
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.
Very nice. But the hasPointerEscape
preconditions need to be defined on the API and enforced.
lib/SIL/Utils/OwnershipUtils.cpp
Outdated
if (auto borrowedValue = BorrowedValue(value)) { | ||
return hasPointerEscape(borrowedValue); | ||
} | ||
for (auto use : value->getUses()) { |
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.
Checking immediate uses only makes sense for an owned value. Do you want an assert here and document that \p value
must introduce an OSSA lifetime (either BorrowedValue or owned value)
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. And added a check in RedundantMoveValueElimination that the original value is owned.
02cff7e
to
7b54b32
Compare
@swift-ci please test |
@swift-ci please test macOS platform |
lib/SIL/Utils/OwnershipUtils.cpp
Outdated
return hasPointerEscape(borrowedValue); | ||
} | ||
assert(value->getOwnershipKind() == OwnershipKind::Owned); | ||
for (auto use : value->getUses()) { |
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.
What if there's an escape in the "extended" lifetime ? i.e a phi values escapes
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.
Thank you, great point. From recent discussion with @atrick, my understanding was that a ForwardingConsumes shouldn't be considered part of the same lifetime for the purposes of pointer escapes. If that applies even to branches, since a br(%owned)
is a forwarding consume of %owned
, it wouldn't be included. On the other hand, excluding phi-extended lifetime is inconsistent with the intuition that "things should be the same" whether (1) there's a merge and a phi or (2) the function body portion is cloned for each incoming value. So it's seeming to me like we do need to look through phis like you say.
If we need to look through phis, phis also probably need to be rejected as inputs to this function like they are rejected by If we need to look through phis, this function need to either reject them (like hasPointerEscape(BorrowedValue)
. It seems we also might not want to count them as "owned value introducers" (or allow them to be used in @atrick's forthcoming OwnedValue
abstraction).hasPointerEscape(BorrowedValue)
) or visit the transitive incoming values, which hasPointerEscape(BorrowedValue)
could be doing as well.
I updated the patch to look through phis and ban them as input and accept them as input by adding transitive incoming values to the worklist.
e6604bd
to
62546a7
Compare
There is a preexisting function with this name that takes a BorrowedValue. The new function calls that preexisting function if a BorrowedValue can be constructed from the SILValue. Otherwise, it looks for direct uses of the value which qualify as "pointer escapes".
Adds to SemanticARCOpts a new step of removing move_value instructions if they are redundant. A move_value is redundant if it adds no new information or optimization opportunities. An example of adding information: a lifetime becoming lexical. The new lifetime's destroys cannot be hoisted over deinit barriers. An example of adding an optimization opportunity: the original value escapes but the value produced by the move_value does not escape. So destroys of the new value can be hoisted more aggressively.
62546a7
to
5f561ed
Compare
@swift-ci please test |
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.
LGTM! Thank you
@swift-ci please clean test linux platform |
1 similar comment
@swift-ci please clean test linux platform |
@swift-ci please smoke test linux platform |
@swift-ci please test linux platform |
Adds to
SemanticARCOpts
a new step of removingmove_value
instructions if they are redundant. Amove_value
is redundant if it adds no new information or optimization opportunities.An example of adding information: a lifetime becoming lexical. The new lifetime's destroys cannot be hoisted over deinit barriers.
An example of adding an optimization opportunity: the original value escapes but the value produced by the
move_value
does not escape. So destroys of the new value can be hoisted more aggressively.