-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Fix KnownSafety optimization bugs in ARCSequenceOpts #33722
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
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.
There is a bunch of refactoring going on here. Can you split that out in a separate PR and land that separately?
SetFactory); | ||
|
||
auto II = this->summarizedinterestinginsts_rbegin(); | ||
auto IE = this->summarizedinterestinginsts_rend(); |
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.
Please remove the usage of this.
Just reading the description, this is incorrect. We only require bottom up that there is a post-dominating use that requires liveness that will not be removed. |
@gottesmm I edited the description of 'KnownSafety' to also include non-arc use. |
7cd553e
to
52bb0ef
Compare
@swift-ci test |
@swift-ci benchmark |
Build failed |
Build failed |
Performance: -O
Code size: -OPerformance: -Osize
Code size: -OsizePerformance: -Onone
Code size: -swiftlibsHow to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
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'm still trying to prove to myself it's correct and efficient.
I was initially worried that this would fail to optimize a more "normal" case like this:
1: retain_value S
2: retain_value S
3: strong_retain S.subobject
4: strong_release S.subobject
5: release_value S
6: release_value S
Maybe that case will actually sill be optimized with your change? Anyway, I won't argue strongly that this pass needs to handle all cases since SemanticARCOpts can handle it eventually.
Will we correctly handle a case like this?
1: retain_value S
2: retain_value S
3: strong_release S.subobject
4: release_value S
5: strong_retain S.subobject
6: release_value S
@atrick We will still optimize the "normal" case. Test |
In:
2 and 4 get paired and optimized away due to CodeMotionSafe. This fix turns off KnownSafety on 2 when it sees 3. |
I'm trying to understand why this known safety fix is looking for retains. Let's say code-motion safe doesn't apply. So what about this?:
|
@atrick Similar to previous example, 3 turns off KnownSafety on 2. And nothing gets optimized if we consider only 'KnownSafety'. |
For efficiency, RefCountInstToMatchedMap can just be a set of unmatched instructions. |
When we summarize the loop in the RefCountInstToMatchedMap. It assumes that the IncToDecStateMap finds any unmatched pair on any paths through the loop. LoopARCSequenceDataflowEvaluator::mergeSuccessors clears the data flow state at any non-local successor, so it should be conservative. This only time this doesn't happen is with "allowsleaks" exist, which reach an unreachable before any side-effect instructions. To be safe, add tests cases for when the release is on the loop tail; add a test:
|
When computing the loop summary, the code assumes that dataflow can be applied to each "interesting" instruction in order to produce a summary. In general this is not sound because loops iterate and the order is meaningless. This means that we're relying on In ARCRegionState::processLoopBottomUp
|
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 asked for some test cases and comments. Otherwise this looks good to me. Thanks!
Regarding the loop data-flow verification, that's a separate issue from this PR so can be done in a follow-up.
While doing bottom up dataflow, if we encounter an unmatched retain instruction, that can pair with a 'KnownSafe' already visited release instruction, we turn off KnownSafety if the two RCIdentities mayAlias. This is done in BottomUpRefCountState::checkAndResetKnownSafety. In order to determine if a retain is umatched, we look at IncToDecStateMap. If a retain was matched during bottom up dataflow, it is always found in IncToDecStateMap with value of the matched release's BottomUpRefCountState. Similarly, during top down dataflow, if we encounter an unmatched release instruction, that can pair with a 'KnownSafe' already visited retain instruction, we turn off KnownSafety if the two RCIdentities mayAlias. This is done in TopDownRefCountState::checkAndResetKnownSafety. In order to determine if a release is umatched, we look at DecToIncStateMap. If a release was matched during top down dataflow, it is always found in DecToIncStateMap with value of the matched retain's TopDownRefCountState. For ARCLoopOpts, during bottom up and top down traversal of a region with a nested loop, we find if the retain/release in the loop summary was matched or not by looking at the persistent RefCountInstToMatched map. This map is populated when processing the nested loop region from the IncToDecStateMap/DecToStateMap which gets thrown away after the loop region is processed. This fixes the bugs in both ARCSequenceOpts without loop support and with loop support.
52bb0ef
to
586de0a
Compare
@swift-ci test |
@swift-ci Please Test Source Compatibility |
Build failed |
Build failed |
@swift-ci Please Test Source Compatibility |
Addressed review comments. |
sck debug failures are pre-existing |
ARCSequenceOpts does KnownSafety optimization where 'KnownSafe' retain/release pairs are deleted.
A retain is 'KnownSafe' if during top down dataflow, it is preceded by another retain or non-arc use on the same RCIdentity.
A release is 'KnownSafe' if during bottom up dataflow, it is preceded by another release or non-arc use on the same RCIdentity.
This PR fixes the following two bugs in KnownSafety optimization.
a) KnownSafety bug in ARCSequenceOpts without loop support
2 and 5 are marked as 'KnownSafe'. And currently they get paired and optimized away. 2 and 5 pairing is incorrect, this can be seen clearly expanding retain_value and release_value.
The correct pairings are 2e and 3, 4 and 5e. Since RCIdentity distinguishes between S and S.subobject we can end
up with incorrect pairings and optimization with KnownSafety. This is true for any aliasing RCIdentities.
b) KnownSafety bug in ARCSequenceOpts with loop support
2 and 6 are marked as 'KnownSafe'. And currently get paired and optimized away. This is incorrect and the correct pairings are 2 and 3 and 4 and 6. ARCLoopOpts computes loop summaries and uses it to only compute refcount states for CodeMotionSafe optimization in ARCSequenceOpts. The instructions in the loop have no effect on the already computed 'KnownSafe' states outside the loop.
With this PR, while doing bottom up dataflow, if we encounter an unmatched retain instruction, that can pair with a 'KnownSafe' already visited release instruction, we turn off KnownSafety if the two
RCIdentities mayAlias.
Similarly, during top down dataflow, if we encounter an unmatched release instruction, that can pair with a 'KnownSafe' already visited retain instruction, we turn off KnownSafety if the two RCIdentities mayAlias. This fixes the bugs in both ARCSequenceOpts without loop support and with loop support.
Fixes rdar://67720198 and rdar://27775427