Skip to content

Commit 538e4b3

Browse files
committed
---
yaml --- r: 347103 b: refs/heads/master c: 90cbb58 h: refs/heads/master i: 347101: 3b556c9 347099: dad5aea 347095: 8c05efc 347087: 4b779c7 347071: fc89d8f
1 parent 2edfffa commit 538e4b3

File tree

10 files changed

+1978
-130
lines changed

10 files changed

+1978
-130
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: e584416210827d9b72c670703a8cfdab6a91c51f
2+
refs/heads/master: 90cbb5827522f1cd70655f098c6f816ad184a6e1
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5036,34 +5036,6 @@ Type ConstraintSystem::simplifyAppliedOverloads(
50365036
break;
50375037
}
50385038

5039-
// Collect the active overload choices.
5040-
SmallVector<OverloadChoice, 4> choices;
5041-
for (auto constraint : disjunction->getNestedConstraints()) {
5042-
if (constraint->isDisabled())
5043-
continue;
5044-
choices.push_back(constraint->getOverloadChoice());
5045-
}
5046-
5047-
// If we can favor one generic result over another, do so.
5048-
if (auto favoredChoice = tryOptimizeGenericDisjunction(choices)) {
5049-
unsigned favoredIndex = favoredChoice - choices.data();
5050-
for (auto constraint : disjunction->getNestedConstraints()) {
5051-
if (constraint->isDisabled())
5052-
continue;
5053-
5054-
if (favoredIndex == 0) {
5055-
if (solverState)
5056-
solverState->favorConstraint(constraint);
5057-
else
5058-
constraint->setFavored();
5059-
5060-
break;
5061-
} else {
5062-
--favoredIndex;
5063-
}
5064-
}
5065-
}
5066-
50675039
// If there was a constraint that we couldn't reason about, don't use the
50685040
// results of any common-type computations.
50695041
if (hasUnhandledConstraints)

trunk/lib/Sema/CSSolver.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,9 +1907,73 @@ void ConstraintSystem::partitionForDesignatedTypes(
19071907
}
19081908
}
19091909

1910+
// Performance hack: if there are two generic overloads, and one is
1911+
// more specialized than the other, prefer the more-specialized one.
1912+
static Constraint *tryOptimizeGenericDisjunction(
1913+
TypeChecker &tc,
1914+
DeclContext *dc,
1915+
ArrayRef<Constraint *> constraints) {
1916+
if (constraints.size() != 2 ||
1917+
constraints[0]->getKind() != ConstraintKind::BindOverload ||
1918+
constraints[1]->getKind() != ConstraintKind::BindOverload ||
1919+
constraints[0]->isFavored() ||
1920+
constraints[1]->isFavored())
1921+
return nullptr;
1922+
1923+
OverloadChoice choiceA = constraints[0]->getOverloadChoice();
1924+
OverloadChoice choiceB = constraints[1]->getOverloadChoice();
1925+
1926+
if (!choiceA.isDecl() || !choiceB.isDecl())
1927+
return nullptr;
1928+
1929+
auto isViable = [](ValueDecl *decl) -> bool {
1930+
assert(decl);
1931+
1932+
auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
1933+
if (!AFD || !AFD->isGeneric())
1934+
return false;
1935+
1936+
auto funcType = AFD->getInterfaceType();
1937+
auto hasAnyOrOptional = funcType.findIf([](Type type) -> bool {
1938+
if (type->getOptionalObjectType())
1939+
return true;
1940+
1941+
return type->isAny();
1942+
});
1943+
1944+
// If function declaration references `Any` or `Any?` type
1945+
// let's not attempt it, because it's unclear
1946+
// without solving which overload is going to be better.
1947+
return !hasAnyOrOptional;
1948+
};
1949+
1950+
auto *declA = choiceA.getDecl();
1951+
auto *declB = choiceB.getDecl();
1952+
1953+
if (!isViable(declA) || !isViable(declB))
1954+
return nullptr;
1955+
1956+
switch (tc.compareDeclarations(dc, declA, declB)) {
1957+
case Comparison::Better:
1958+
return constraints[0];
1959+
1960+
case Comparison::Worse:
1961+
return constraints[1];
1962+
1963+
case Comparison::Unordered:
1964+
return nullptr;
1965+
}
1966+
}
1967+
19101968
void ConstraintSystem::partitionDisjunction(
19111969
ArrayRef<Constraint *> Choices, SmallVectorImpl<unsigned> &Ordering,
19121970
SmallVectorImpl<unsigned> &PartitionBeginning) {
1971+
// Apply a special-case rule for favoring one generic function over
1972+
// another.
1973+
if (auto favored = tryOptimizeGenericDisjunction(TC, DC, Choices)) {
1974+
favorConstraint(favored);
1975+
}
1976+
19131977
SmallSet<Constraint *, 16> taken;
19141978

19151979
// Local function used to iterate over the untaken choices from the
@@ -1932,6 +1996,7 @@ void ConstraintSystem::partitionDisjunction(
19321996
// end of the partitioning.
19331997

19341998
SmallVector<unsigned, 4> favored;
1999+
SmallVector<unsigned, 4> simdOperators;
19352000
SmallVector<unsigned, 4> disabled;
19362001
SmallVector<unsigned, 4> unavailable;
19372002

@@ -1971,6 +2036,22 @@ void ConstraintSystem::partitionDisjunction(
19712036
});
19722037
}
19732038

2039+
// Partition SIMD operators.
2040+
if (!TC.getLangOpts().SolverEnableOperatorDesignatedTypes &&
2041+
isOperatorBindOverload(Choices[0])) {
2042+
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
2043+
if (!isOperatorBindOverload(constraint))
2044+
return false;
2045+
2046+
if (isSIMDOperator(constraint->getOverloadChoice().getDecl())) {
2047+
simdOperators.push_back(index);
2048+
return true;
2049+
}
2050+
2051+
return false;
2052+
});
2053+
}
2054+
19742055
// Local function to create the next partition based on the options
19752056
// passed in.
19762057
PartitionAppendCallback appendPartition =
@@ -1994,6 +2075,7 @@ void ConstraintSystem::partitionDisjunction(
19942075
});
19952076
appendPartition(favored);
19962077
appendPartition(everythingElse);
2078+
appendPartition(simdOperators);
19972079

19982080
// Now create the remaining partitions from what we previously collected.
19992081
appendPartition(unavailable);

trunk/lib/Sema/ConstraintSystem.cpp

Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,92 +1371,6 @@ ConstraintSystem::getTypeOfMemberReference(
13711371
return { openedType, type };
13721372
}
13731373

1374-
// Performance hack: if there are two generic overloads, and one is
1375-
// more specialized than the other, prefer the more-specialized one.
1376-
OverloadChoice *ConstraintSystem::tryOptimizeGenericDisjunction(
1377-
ArrayRef<OverloadChoice> choices) {
1378-
if (choices.size() != 2)
1379-
return nullptr;
1380-
1381-
const auto &choiceA = choices[0];
1382-
const auto &choiceB = choices[1];
1383-
1384-
if (!choiceA.isDecl() || !choiceB.isDecl())
1385-
return nullptr;
1386-
1387-
auto isViable = [](ValueDecl *decl) -> bool {
1388-
assert(decl);
1389-
1390-
auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
1391-
if (!AFD || !AFD->isGeneric())
1392-
return false;
1393-
1394-
auto funcType = AFD->getInterfaceType();
1395-
auto hasAnyOrOptional = funcType.findIf([](Type type) -> bool {
1396-
if (type->getOptionalObjectType())
1397-
return true;
1398-
1399-
return type->isAny();
1400-
});
1401-
1402-
// If function declaration references `Any` or `Any?` type
1403-
// let's not attempt it, because it's unclear
1404-
// without solving which overload is going to be better.
1405-
return !hasAnyOrOptional;
1406-
};
1407-
1408-
auto *declA = choiceA.getDecl();
1409-
auto *declB = choiceB.getDecl();
1410-
1411-
if (!isViable(declA) || !isViable(declB))
1412-
return nullptr;
1413-
1414-
switch (TC.compareDeclarations(DC, declA, declB)) {
1415-
case Comparison::Better:
1416-
return const_cast<OverloadChoice *>(&choiceA);
1417-
1418-
case Comparison::Worse:
1419-
return const_cast<OverloadChoice *>(&choiceB);
1420-
1421-
case Comparison::Unordered:
1422-
return nullptr;
1423-
}
1424-
}
1425-
1426-
/// If there are any SIMD operators in the overload set, partition the set so
1427-
/// that the SIMD operators come at the end.
1428-
static ArrayRef<OverloadChoice> partitionSIMDOperators(
1429-
ArrayRef<OverloadChoice> choices,
1430-
SmallVectorImpl<OverloadChoice> &scratch) {
1431-
// If the first element isn't an operator, none of them are.
1432-
if (!choices[0].isDecl() ||
1433-
!isa<FuncDecl>(choices[0].getDecl()) ||
1434-
!cast<FuncDecl>(choices[0].getDecl())->isOperator() ||
1435-
choices[0].getDecl()->getASTContext().LangOpts
1436-
.SolverEnableOperatorDesignatedTypes)
1437-
return choices;
1438-
1439-
// Check whether we have any SIMD operators.
1440-
bool foundSIMDOperator = false;
1441-
for (const auto &choice : choices) {
1442-
if (isSIMDOperator(choice.getDecl())) {
1443-
foundSIMDOperator = true;
1444-
break;
1445-
}
1446-
}
1447-
1448-
if (!foundSIMDOperator)
1449-
return choices;
1450-
1451-
scratch.assign(choices.begin(), choices.end());
1452-
std::stable_partition(scratch.begin(), scratch.end(),
1453-
[](const OverloadChoice &choice) {
1454-
return !isSIMDOperator(choice.getDecl());
1455-
});
1456-
1457-
return scratch;
1458-
}
1459-
14601374
Type ConstraintSystem::getEffectiveOverloadType(const OverloadChoice &overload,
14611375
bool allowMembers,
14621376
DeclContext *useDC) {
@@ -1576,12 +1490,6 @@ void ConstraintSystem::addOverloadSet(Type boundType,
15761490
return;
15771491
}
15781492

1579-
if (!favoredChoice)
1580-
favoredChoice = tryOptimizeGenericDisjunction(choices);
1581-
1582-
SmallVector<OverloadChoice, 4> scratchChoices;
1583-
choices = partitionSIMDOperators(choices, scratchChoices);
1584-
15851493
SmallVector<Constraint *, 4> overloads;
15861494

15871495
// As we do for other favored constraints, if a favored overload has been

trunk/lib/Sema/ConstraintSystem.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,10 +1352,10 @@ class ConstraintSystem {
13521352
/// Favor the given constraint; this change will be rolled back
13531353
/// when we exit the current solver scope.
13541354
void favorConstraint(Constraint *constraint) {
1355-
if (!constraint->isFavored()) {
1356-
constraint->setFavored();
1357-
favoredConstraints.push_back(constraint);
1358-
}
1355+
assert(!constraint->isFavored());
1356+
1357+
constraint->setFavored();
1358+
favoredConstraints.push_back(constraint);
13591359
}
13601360

13611361
private:
@@ -2085,6 +2085,20 @@ class ConstraintSystem {
20852085
removeInactiveConstraint(constraint);
20862086
}
20872087

2088+
/// Note that this constraint is "favored" within its disjunction, and
2089+
/// should be tried first to the exclusion of non-favored constraints in
2090+
/// the same disjunction.
2091+
void favorConstraint(Constraint *constraint) {
2092+
if (constraint->isFavored())
2093+
return;
2094+
2095+
if (solverState) {
2096+
solverState->favorConstraint(constraint);
2097+
} else {
2098+
constraint->setFavored();
2099+
}
2100+
}
2101+
20882102
/// Retrieve the list of inactive constraints.
20892103
ConstraintList &getConstraints() { return InactiveConstraints; }
20902104

@@ -3187,11 +3201,6 @@ class ConstraintSystem {
31873201

31883202
Constraint *selectApplyDisjunction();
31893203

3190-
/// Look at the set of overload choices to determine if there is a best
3191-
/// generic overload to favor.
3192-
OverloadChoice *tryOptimizeGenericDisjunction(
3193-
ArrayRef<OverloadChoice> choices);
3194-
31953204
/// Solve the system of constraints generated from provided expression.
31963205
///
31973206
/// \param expr The expression to generate constraints from.

trunk/stdlib/public/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ set(SWIFTLIB_SOURCES
200200
${SWIFTLIB_ESSENTIAL}
201201
### PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER ###
202202
Availability.swift
203+
CollectionDifference.swift
203204
CollectionOfOne.swift
205+
Diffing.swift
204206
ExistentialCollection.swift.gyb
205207
Mirror.swift
206208
PlaygroundDisplay.swift

0 commit comments

Comments
 (0)