Skip to content

ARCAnalysis: fix canNeverUseObject to correctly handle builtins. #25985

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

Merged
merged 1 commit into from
Jul 8, 2019
Merged

ARCAnalysis: fix canNeverUseObject to correctly handle builtins. #25985

merged 1 commit into from
Jul 8, 2019

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Jul 6, 2019

This analysis helper was inverting the result for builtins. Builtins
such as "copyMemory" were treated as never using a value.

This manifested in a crash in TestFoundation. NSDictionary's
initializer released the incoming array before copying it. This
crashed later during dictionary destruction.

The crash was hidden by a secondary bug in mayHaveSymmetricInterference
that effectively ignored the result from canNeverUseValue.

Rename the helper to canUseObject, invert the result for builtins, and
fix mayHaveSymmetricInterference to respect the result of
canUseObject.

Note that instructions that cannot access a referenced object
obviously cannot not "interfere" with a release.

Fixing these bugs now allows ARC optimization around dealloc_stack and
other operations that don't care about the reference count.

@atrick
Copy link
Contributor Author

atrick commented Jul 6, 2019

@swift-ci test.

@atrick atrick requested a review from gottesmm July 6, 2019 00:27
@atrick
Copy link
Contributor Author

atrick commented Jul 6, 2019

@swift-ci test source compatibility

@atrick
Copy link
Contributor Author

atrick commented Jul 6, 2019

@swift-ci benchmark

@swift-ci
Copy link
Contributor

swift-ci commented Jul 6, 2019

Performance: -O

Regression OLD NEW DELTA RATIO
StringWalk 600 760 +26.7% 0.79x
SequenceAlgosRange 1190 1300 +9.2% 0.92x (?)
Chars2 3050 3300 +8.2% 0.92x (?)
MapReduceLazyCollectionShort 26 28 +7.7% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
DropFirstArray 26 13 -50.0% 2.00x
DataCountSmall 17 10 -41.2% 1.70x
DataSubscriptSmall 17 13 -23.5% 1.31x (?)
DataCountMedium 17 13 -23.5% 1.31x (?)
Dictionary4 194 155 -20.1% 1.25x (?)
FlattenListFlatMap 5105 4133 -19.0% 1.24x (?)
RemoveWhereMoveStrings 433 355 -18.0% 1.22x (?)
DropFirstSequence 33 29 -12.1% 1.14x
DropFirstSequenceLazy 33 29 -12.1% 1.14x (?)
Dictionary4OfObjects 225 198 -12.0% 1.14x (?)
Set.isStrictSubset.Int.Empty 52 47 -9.6% 1.11x (?)
DataSubscriptMedium 37 34 -8.1% 1.09x (?)
StrToInt 960 890 -7.3% 1.08x (?)
ObjectiveCBridgeStubFromNSDateRef 2600 2420 -6.9% 1.07x (?)

Code size: -O

Improvement OLD NEW DELTA RATIO
DropFirst.o 24419 23795 -2.6% 1.03x
ReversedCollections.o 11611 11451 -1.4% 1.01x
RomanNumbers.o 8483 8371 -1.3% 1.01x

Performance: -Osize

Regression OLD NEW DELTA RATIO
ArrayAppendSequence 680 850 +25.0% 0.80x (?)
CharIteration_punctuated_unicodeScalars 400 440 +10.0% 0.91x (?)
DataSubscriptMedium 34 37 +8.8% 0.92x (?)
CharIteration_tweet_unicodeScalars 3440 3720 +8.1% 0.92x (?)
MapReduceLazyCollectionShort 26 28 +7.7% 0.93x (?)
UTF8Decode_InitFromData 119 128 +7.6% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
SumUsingReduce 440 282 -35.9% 1.56x
RemoveWhereMoveStrings 428 354 -17.3% 1.21x (?)
DropWhileAnySeqCntRange 111 97 -12.6% 1.14x (?)
RemoveWhereSwapInts 37 34 -8.1% 1.09x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 28800 26600 -7.6% 1.08x (?)
RomanNumbers2 394 367 -6.9% 1.07x (?)

Code size: -Osize

Performance: -Onone

Regression OLD NEW DELTA RATIO
SubstringFromLongString 9 10 +11.1% 0.90x (?)
 
Improvement OLD NEW DELTA RATIO
ArrayOfGenericPOD2 793 715 -9.8% 1.11x (?)
ArrayOfPOD 725 662 -8.7% 1.10x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 30000 27800 -7.3% 1.08x (?)

Code size: -swiftlibs

Improvement OLD NEW DELTA RATIO
libswiftCoreGraphics.dylib 65536 61440 -6.2% 1.07x
How to read the data The 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
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 64 GB

@swift-ci
Copy link
Contributor

swift-ci commented Jul 6, 2019

Build failed
Swift Test Linux Platform
Git Sha - 4d10a8416717925d4dec4a19aea2cdabf0723dba

@gottesmm
Copy link
Contributor

gottesmm commented Jul 6, 2019

Nice catch!

if (!canNeverUseValues(&I) || I.mayReleaseOrReadRefCount() ||
// FIXME: mayReleaseOrReadRefCount should be a strict subset of
// canUseObject. If not, there is a bug in canUseObject.
if (canUseObject(&I) || I.mayReleaseOrReadRefCount() ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it should be a strict subset, why not just put in an assert (maybe you do not feel comfortable with relying since you haven't done a go over?).

Even if you don't feel comfortable with that (i.e. you want us to be conservatively correct in non-asserts builds), we should have an assert here to track down the issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is currently dead and the FIXME is just speculation. I added it as a note to whomever looks at the code again soon in case we temporarily resurrect it. I think that will be the time to clean it up. I didn't want to potentially change the original behavior without testing it. At some not-to-distant point the code will be deleted anyway.

This analysis helper was inverting the result for builtins. Builtins
such as "copyMemory" were treated as never using a value.

This manifested in a crash in TestFoundation. NSDictionary's
initializer released the incoming array before copying it. This
crashed later during dictionary destruction.

The crash was hidden by a secondary bug in mayHaveSymmetricInterference
that effectively ignored the result from canNeverUseValue.

Rename the helper to canUseObject, invert the result for builtins, and
fix mayHaveSymmetricInterference to respect the result of
canUseObject.

Note that instructions that cannot access a referenced object
obviously cannot not "interfere" with a release.

Fixing these bugs now allows ARC optimization around dealloc_stack and
other operations that don't care about the reference count.
@atrick
Copy link
Contributor Author

atrick commented Jul 8, 2019

@swift-ci test

@swift-ci
Copy link
Contributor

swift-ci commented Jul 8, 2019

Build failed
Swift Test Linux Platform
Git Sha - 4d10a8416717925d4dec4a19aea2cdabf0723dba

@swift-ci
Copy link
Contributor

swift-ci commented Jul 8, 2019

Build failed
Swift Test OS X Platform
Git Sha - 4d10a8416717925d4dec4a19aea2cdabf0723dba

@atrick
Copy link
Contributor Author

atrick commented Jul 8, 2019

@swift-ci smoke test linux

1 similar comment
@atrick
Copy link
Contributor Author

atrick commented Jul 8, 2019

@swift-ci smoke test linux

@atrick atrick merged commit 7bc5c50 into swiftlang:master Jul 8, 2019
@atrick atrick deleted the fix-arc-builtin branch July 30, 2019 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants