Skip to content

[CSBindings] Try Void as a binding for closure result type variable #15134

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
Mar 12, 2018

Conversation

xedin
Copy link
Contributor

@xedin xedin commented Mar 10, 2018

If we could find a binding for type variable representing closure result
let's also add implicit Void type as another pontential binding to attempt
because there is an implicit conversion from () -> T to () -> Void
so finding Void early is going to help avoid function conversions down
the line.

Resolves: rdar://problem/37790062

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

@swift-ci please test

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

@swift-ci please test source compatibility

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

/cc @slavapestov since we have determineBestBindings look for related type inferable from subtype constraints this is going to make it so Void is inferred directly when possible, so no changes to CSApply to IRGen are required.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - e24c0d3654e1f97e54fda781459319b91a5d6b75

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - e24c0d3654e1f97e54fda781459319b91a5d6b75

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

@swift-ci please test macOS platform

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

Looks like Linux is still broken :(

@slavapestov
Copy link
Contributor

@xedin I'm not familiar with this code, I think @rudkx should review it. But if you want to test for the absence of a function conversion thunk, don't you need to write a SILGen test?

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

@slavapestov I just wanted to run source compatibility first to make sure that I didn't break anything :) I'll add couple more tests to SILGen.

@xedin xedin requested a review from rudkx March 10, 2018 05:25
@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

/cc @rudkx please take a look, I can't figure out safer fix for this... (I've reverted changes to ClosureResult + IRGen since C style functions don't support thunks like that).

@xedin
Copy link
Contributor Author

xedin commented Mar 10, 2018

@swift-ci please test Linux platform

If we could find a binding for type variable representing closure result
let's also add implicit `Void` type as another pontential binding to attempt
because there is an implicit conversion from `() -> T` to `() -> Void`
so finding `Void` early is going to help avoid function conversions down
the line.

Resolves: rdar://problem/37790062
@xedin xedin force-pushed the rdar-37790062-v3 branch from e24c0d3 to 18d2c1d Compare March 11, 2018 08:42
@xedin
Copy link
Contributor Author

xedin commented Mar 11, 2018

Rebased the changes to getPotentialBindings

@xedin
Copy link
Contributor Author

xedin commented Mar 11, 2018

@swift-ci please test

@xedin
Copy link
Contributor Author

xedin commented Mar 11, 2018

@swift-ci please test source compatibility

@swiftlang swiftlang deleted a comment from swift-ci Mar 11, 2018
@swiftlang swiftlang deleted a comment from swift-ci Mar 12, 2018
@xedin
Copy link
Contributor Author

xedin commented Mar 12, 2018

@swift-ci please test Linux platform

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

@xedin xedin merged commit 94dbbd7 into swiftlang:master Mar 12, 2018
Copy link
Contributor

@rudkx rudkx left a comment

Choose a reason for hiding this comment

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

Otherwise LGTM.


if (auto *locator = typeVar->getImpl().getLocator()) {
auto path = locator->getPath();
auto voidType = TupleType::getEmpty(getASTContext());
Copy link
Contributor

Choose a reason for hiding this comment

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

ASTContext has TheEmptyTupleType for this (and it's already a CanType).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Included the fix to #15187

@davezarzycki
Copy link
Contributor

This change broke Swift on Fedora Linux 27 (built with clang+llvm ToT). The following validation tests hang:

compiler_crashers_fixed/28684-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
compiler_crashers_fixed/28686-swift-typebase-getcanonicaltype.swift

@davezarzycki
Copy link
Contributor

Backtraces (albeit Release+Assert):

http://znu.io/lldb-28684.out
http://znu.io/lldb-28686.out

@davezarzycki
Copy link
Contributor

Well look at that. "Hang" turns out to be relative. The test suite takes 10x longer on my box after this pull request. Regardless, this seems like a massive performance regression.

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

@davezarzycki Are you sure that it's this change? It's only related to closure result type variable handling, in couple of narrow cases.

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

@davezarzycki It doesn't seem like ci.swift.org reports that behavior change in build tests before and after this PR went it, all of the incremental builds take ~1 hour.

@davezarzycki
Copy link
Contributor

I just reverified that this PR is the source of the regression. Pull #15172 was merged before this PR, and that doesn't have the performance regression, therefore this PR is the source of the problem.

I'm not surprised the build bots mask the problem. They're slow. My Linux box can do a clean build and run validation suite (sans stress tests) in just a few minutes. Therefore this performance regression is quite obvious. :-/

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

Do you have any examples of expressions which became slower? 10x performance regression is not something which should leave CI times unchanged (theoretically that is).

@davezarzycki
Copy link
Contributor

How do I extract the slow expressions from the tests that are slower?

The test suite performance is a great example of Amdahl's Law. With just a few cores, having one test become 10x longer is hard to notice, but with many cores, one test getting longer is quite noticeable.

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

Are you only talking about two tests you have mentioned? If so, they are pretty expreme cases of auto-generated code I am surprised that they don’t result in “expression to complex” to be honest. Don’t see a reason to revert this just based on such failures.

@davezarzycki
Copy link
Contributor

Yes, just the two two tests. They run for almost exactly ten minutes each then exit after this PR. Here is some perf output, if it helps:

Samples: 1M of event 'cycles:uppp', Event count (approx.): 1029367409751
  Overhead  Command  Shared Object        Symbol
+   12.77%  swift    swift                [.] swift::constraints::ConstraintGraph::lookupNode
+    8.27%  swift    swift                [.] swift::constraints::ConstraintGraph::gatherConstraints
+    7.65%  swift    swift                [.] llvm::SmallPtrSetImpl<swift::TypeVariableType*>::insert
+    6.20%  swift    swift                [.] swift::TypeVariableType::Implementation::getRepresentative
+    5.96%  swift    swift                [.] swift::constraints::ConstraintGraphNode::getAdjacency
+    5.21%  swift    swift                [.] swift::Type::transformRec
+    4.74%  swift    swift                [.] connectedComponentsDFS
     4.21%  swift    swift                [.] swift::constraints::ConstraintGraph::computeConnectedComponents
+    3.17%  swift    swift                [.] swift::constraints::ConstraintSystem::determineBestBindings
+    2.76%  swift    swift                [.] llvm::function_ref<swift::Type (swift::Type)>::callback_fn<swift::Type simplifyTypeImpl<swift::constraints::ConstraintSystem::simplifyType(swift::Type)::$_7>(swift::constraints
+    2.28%  swift    swift                [.] swift::constraints::ConstraintGraphNode::getEquivalenceClass
+    2.23%  swift    swift                [.] swift::constraints::ConstraintSystem::getPotentialBindings
+    2.13%  swift    swift                [.] llvm::SmallPtrSetImplBase::insert_imp_big
+    2.11%  swift    swift                [.] llvm::DenseMapBase<llvm::DenseMap<std::pair<swift::Type, std::pair<swift::Type, unsigned int> >, swift::FunctionType*, llvm::DenseMapInfo<std::pair<swift::Type, std::pair<swift
     1.91%  swift    swift                [.] swift::constraints::ConstraintSystem::solveRec
+    1.55%  swift    swift                [.] llvm::SmallVectorImpl<swift::constraints::ConstraintSystem::PotentialBinding>::operator=
+    1.50%  swift    swift                [.] llvm::function_ref<llvm::Optional<swift::Type> (swift::TypeBase*)>::callback_fn<swift::Type::transform(llvm::function_ref<swift::Type (swift::Type)>) const::$_15>
+    1.47%  swift    swift                [.] swift::constraints::ConstraintGraph::contractEdges
+    1.32%  swift    swift                [.] swift::constraints::ConstraintSystem::matchTypes
+    1.15%  swift    swift                [.] swift::constraints::ConstraintSystem::getPotentialBindingForRelationalConstraint
+    1.12%  swift    swift                [.] (anonymous namespace)::Traversal::visitAnyFunctionType
+    0.82%  swift    swift                [.] llvm::SmallPtrSetImplBase::FindBucketFor
+    0.79%  swift    swift                [.] llvm::SmallPtrSetImpl<swift::TypeVariableType*>::count
+    0.79%  swift    swift                [.] swift::TypeVisitor<(anonymous namespace)::Traversal, bool>::visit
+    0.78%  swift    swift                [.] llvm::SmallPtrSetImpl<swift::constraints::Constraint*>::insert
+    0.77%  swift    swift                [.] llvm::SmallPtrSetImplBase::Grow
+    0.76%  swift    swift                [.] swift::constraints::ConstraintSystem::matchFunctionTypes
+    0.72%  swift    swift                [.] llvm::SmallPtrSetImplBase::SmallPtrSetImplBase
+    0.65%  swift    swift                [.] llvm::DenseMapBase<llvm::SmallDenseMap<swift::TypeVariableType*, swift::constraints::ConstraintSystem::PotentialBindings, 4u, llvm::DenseMapInfo<swift::TypeVariableType*>, llvm
+    0.63%  swift    swift                [.] llvm::DenseMapBase<llvm::DenseMap<swift::constraints::Constraint*, unsigned int, llvm::DenseMapInfo<swift::constraints::Constraint*>, llvm::detail::DenseMapPair<swift::constrai

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

Thanks! I will re-adjust the tests in the separate PR then.

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

It's weird that on Linux it's so much slower - I just ran one of the tests locally and it only took 1.56s to complete.

@davezarzycki
Copy link
Contributor

Ya, I observed that at first too. Once I copied the exact process arguments from the output of ps axww, I was able to reproduce this. Which did you do?

@davezarzycki
Copy link
Contributor

It seems that the interaction of this pull request and -swift-version 3 (as invoked by the test suite) causes one of the two tests to become slow. I haven't checked the other. Does this help?

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

@davezarzycki I just ran it using --test-paths option via ./utils/build-script that would involve lit on the specific file/directory which represents the way CI runs the tests too.

@davezarzycki
Copy link
Contributor

Weird. I don't personally care about the performance of -swift-version 3. Can we force these tests to use the current version of the language? And for whatever it may be worth, without -swift-version 3, the tests finish in about 10 and 20 seconds respectively, which is still dramatically slower than 1.56 seconds on your computer. Very weird.

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

I think it's okay if we remove swift-version from the test, since they are trying to make sure that we don't crash trying to solve this anyway. But I'm curious, if you remove -swift-version 3 how long do these tests take on your machine?

@davezarzycki
Copy link
Contributor

10 and 20 seconds respectively, as I just wrote.

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

Ah sorry I misread that, how about with -swift-version 3 then?

@davezarzycki
Copy link
Contributor

They both seem to time out precisely after 10 minutes.

@davezarzycki
Copy link
Contributor

That's probably because 'not' and/or test harness itself assumes success if it these two tests haven't crashed in 10 minutes. :-/

@xedin
Copy link
Contributor Author

xedin commented Mar 13, 2018

I just extracted the command line for the first test you mentioned and try to run it with and without -swift-version 3 and it's pretty much the same result on macOS (DebugAssert build) so I'm wondering what is so special about Linux in this case, since solver should behave the same regardless what platform it's run on.

Anyway, I'll modify these tests to limit type-checker runtime to 1 second which is good anyway.

@davezarzycki
Copy link
Contributor

I'm running Release-Assert, if it matters.

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.

6 participants