Skip to content

Conversation

DougGregor
Copy link
Member

Rather than having the type checker look for the specific witness to
next() when type checking the for-each loop, which had the effect of
devirtualizing next() even when it shouldn't be, leave the formation
of the next() reference to SILGen. There, form it as a witness
reference, so that the SIL optimizer can choose whether to
devirtualization (or not).

…olver.

The type checking of the for-each loop is split between the constraint
solver (which does most of the work) and the statement checker (which
updates the for-each loop AST). Move more of the work into the constraint
solver proper, so that the AST updates can happen in one place, making use
of the solution produced by the solver. This allows a few things, some of
which are short-term gains and others that are more future-facing:

* `TypeChecker::convertToType` has been removed, because we can now either
use the more general `typeCheckExpression` entry point or perform the
appropriate operation within the constraint system.
* Solving the constraint system ensures that everything related to the
for-each loop full checks out
* Additional refactoring will make it easier for the for-each loop to be
checked as part of a larger constraint system, e.g., for processing entire
closures or function bodies (that’s the futurist bit).
Introduce a new kind of constraint, the "value witness" constraint,
which captures a reference to a witness for a specific protocol
conformance. It otherwise acts like a more restricted form of a "value
member" constraint, where the specific member is known (as a
ValueDecl*) in advance.

The constraint is effectively dependent on the protocol
conformance itself; if that conformance fails, mark the type variables
in the resolved member type as "holes", so that the conformance
failure does not cascade.

Note that the resolved overload for this constraint always refers to
the requirement, rather than the witness, so we will end up recording
witness-method references in the AST rather than concrete references,
and leave it up to the optimizers to perform devirtualization. This is
demonstrated by the SIL changes needed in tests, and is part of the
wider resilience issue with conformances described by
rdar://problem/22708391.
…lution.

While this doesn't completely use the solution's set of known conformances,
it moves the logic for handling the lookup into the right place.
Rather than having the type checker form the ConcreteDeclRef for
makeIterator, have SILGen do it, because it's fairly trivial.
Eliminates some redundant state from the AST.
…next().

Rather than having the type checker look for the specific witness to
next() when type checking the for-each loop, which had the effect of
devirtualizing next() even when it shouldn't be, leave the formation
of the next() reference to SILGen. There, form it as a witness
reference, so that the SIL optimizer can choose whether to
devirtualization (or not).
@DougGregor
Copy link
Member Author

@swift-ci please smoke test

@DougGregor
Copy link
Member Author

@swift-ci please benchmark

@DougGregor
Copy link
Member Author

This is a follow-on to #28380

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

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

I have left a comment about a "fix" inline, otherwise looks great!

recordPotentialHole(typeVar);
});

return SolutionKind::Solved;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to record AddMissingConformance fix here otherwise we might produce a solution with holes but without any fixes which would crash later in either verifier (in debug build) or SILGen (in release).

Copy link
Member Author

Choose a reason for hiding this comment

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

Huh, okay. I guess it's fine to have redundant missing-conformance fixes?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, they going to get coalesced into one for the same locator.

@swift-ci
Copy link
Contributor

swift-ci commented Jan 2, 2020

Performance: -O

Regression OLD NEW DELTA RATIO
LazilyFilteredArrayContains 29500 35600 +20.7% 0.83x
Dictionary4 243 265 +9.1% 0.92x (?)
FlattenListLoop 4085 4446 +8.8% 0.92x (?)
RemoveWhereSwapInts 60 65 +8.3% 0.92x (?)
MapReduceClass2 37 40 +8.1% 0.93x (?)
MapReduce 371 400 +7.8% 0.93x (?)
MapReduceAnyCollection 369 397 +7.6% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
DropFirstAnySequenceLazy 2785 1873 -32.7% 1.49x
Data.init.Sequence.64kB.Count.RE.I 128 114 -10.9% 1.12x (?)
CharacterLiteralsLarge 108 97 -10.2% 1.11x
Data.init.Sequence.64kB.Count.RE 126 114 -9.5% 1.11x (?)
DataSetCountSmall 154 142 -7.8% 1.08x (?)

Code size: -O

Performance: -Osize

Regression OLD NEW DELTA RATIO
PrefixWhileAnyCollectionLazy 159 176 +10.7% 0.90x (?)
FlattenListLoop 4077 4443 +9.0% 0.92x (?)
Array2D 6928 7520 +8.5% 0.92x (?)
RandomShuffleLCG2 768 832 +8.3% 0.92x (?)
RemoveWhereSwapInts 63 68 +7.9% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
DropFirstAnySequenceLazy 3181 2110 -33.7% 1.51x (?)
StringBuilderLong 1320 1180 -10.6% 1.12x (?)
DropWhileAnySeqCRangeIter 180 163 -9.4% 1.10x (?)
DropWhileAnySeqCntRange 198 181 -8.6% 1.09x (?)
DataSetCountSmall 157 145 -7.6% 1.08x
StringComparison_fastPrenormal 1000 930 -7.0% 1.08x (?)

Code size: -Osize

Performance: -Onone

Regression OLD NEW DELTA RATIO
DictionarySubscriptDefaultMutationArray 4666 12730 +172.8% 0.37x
DictionarySubscriptDefaultMutation 4506 11793 +161.7% 0.38x
FrequenciesUsingReduceInto 3991 9827 +146.2% 0.41x
DictionarySubscriptDefaultMutationOfObjects 8380 15920 +90.0% 0.53x
DictionarySubscriptDefaultMutationArrayOfObjects 10620 18880 +77.8% 0.56x
FrequenciesUsingReduce 9412 15566 +65.4% 0.60x
StringRemoveDupes 778 970 +24.7% 0.80x
DictionaryRemove 13430 16560 +23.3% 0.81x (?)
DictionaryBridgeToObjC_Access 1046 1250 +19.5% 0.84x (?)
SetUnionInt100 346 404 +16.8% 0.86x
DictionaryCompactMapValuesOfCastValue 60534 67284 +11.2% 0.90x (?)
SetUnionInt50 515 570 +10.7% 0.90x
Dictionary3 583 644 +10.5% 0.91x (?)
Prims.NonStrongRef.Unmanaged 1620 1787 +10.3% 0.91x (?)
SetUnionInt25 580 638 +10.0% 0.91x
Set.filter.Int100.24k 4017 4389 +9.3% 0.92x
Dictionary4 925 1009 +9.1% 0.92x (?)
Set.filter.Int100.20k 3424 3732 +9.0% 0.92x
SetIntersectionInt100 878 955 +8.8% 0.92x (?)
Dictionary3OfObjects 1442 1568 +8.7% 0.92x (?)
Set.filter.Int50.24k 2466 2681 +8.7% 0.92x
Set.filter.Int50.20k 2087 2264 +8.5% 0.92x (?)
Set.filter.Int100.16k 2910 3154 +8.4% 0.92x (?)
DataCreateEmptyArray 66550 72050 +8.3% 0.92x (?)
Dictionary4Legacy 1181 1278 +8.2% 0.92x (?)
DictionarySwapAt 3860 4176 +8.2% 0.92x (?)
SetSymmetricDifferenceInt25 776 839 +8.1% 0.92x
Dictionary4OfObjects 1340 1448 +8.1% 0.93x (?)
DictionaryRemoveOfObjects 44600 48100 +7.8% 0.93x (?)
Set.filter.Int50.16k 1755 1892 +7.8% 0.93x (?)
Set.filter.Int50.28k 3197 3441 +7.6% 0.93x (?)
Set.filter.Int100.28k 5383 5793 +7.6% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
ArrayAppendLatin1 30872 25092 -18.7% 1.23x (?)
ArrayAppendAscii 30532 24820 -18.7% 1.23x (?)
ArrayAppendUTF16 30566 24990 -18.2% 1.22x (?)
DataAccessBytesMedium 175 161 -8.0% 1.09x (?)

Code size: -swiftlibs

Regression OLD NEW DELTA RATIO
libswiftCore.dylib 3768320 3837952 +1.8% 0.98x
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 Pro
  Model Identifier: MacPro6,1
  Processor Name: 12-Core Intel Xeon E5
  Processor Speed: 2.7 GHz
  Number of Processors: 1
  Total Number of Cores: 12
  L2 Cache (per Core): 256 KB
  L3 Cache: 30 MB
  Memory: 16 GB

@DougGregor DougGregor merged commit 7977643 into swiftlang:master Jan 3, 2020
@DougGregor DougGregor deleted the de-de-virtualize-for-each branch January 3, 2020 01:09
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