Skip to content

Commit c9100c4

Browse files
committed
[ConstraintSystem] Instead of favoring existing operator bindings,
order them first in the main disjunction partition.
1 parent 8dd2008 commit c9100c4

File tree

1 file changed

+24
-41
lines changed

1 file changed

+24
-41
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,7 +2015,9 @@ static Constraint *tryOptimizeGenericDisjunction(
20152015

20162016
// Performance hack: favor operator overloads with decl or type we're already
20172017
// binding elsewhere in this expression.
2018-
static void existingOperatorBindingsForDisjunction(ConstraintSystem &CS, ArrayRef<Constraint *> constraints, SmallVectorImpl<Constraint *> &found) {
2018+
static void existingOperatorBindingsForDisjunction(ConstraintSystem &CS,
2019+
ArrayRef<Constraint *> constraints,
2020+
SmallVectorImpl<unsigned> &found) {
20192021
auto *choice = constraints.front();
20202022
if (choice->getKind() != ConstraintKind::BindOverload)
20212023
return;
@@ -2026,59 +2028,35 @@ static void existingOperatorBindingsForDisjunction(ConstraintSystem &CS, ArrayRe
20262028
auto decl = overload.getDecl();
20272029
if (!decl->isOperator())
20282030
return;
2029-
auto baseName = decl->getBaseName();
2030-
2031-
SmallSet<TypeBase *, 8> typesFound;
20322031

2032+
SmallSet<CanType, 8> typesFound;
20332033
for (auto overload : CS.getResolvedOverloads()) {
20342034
auto resolved = overload.second;
20352035
if (!resolved.choice.isDecl())
20362036
continue;
2037-
auto representativeDecl = resolved.choice.getDecl();
20382037

2038+
auto representativeDecl = resolved.choice.getDecl();
20392039
if (!representativeDecl->isOperator())
20402040
continue;
20412041

2042-
if (representativeDecl->getBaseName() == baseName) {
2043-
// Favor exactly the same decl, if we have a binding to the same name.
2044-
for (auto *constraint : constraints) {
2045-
if (constraint->isFavored())
2046-
continue;
2047-
auto choice = constraint->getOverloadChoice();
2048-
if (choice.getDecl() == representativeDecl) {
2049-
found.push_back(constraint);
2050-
break;
2051-
}
2052-
}
2053-
} else {
2054-
// Favor the same type, if we have a binding to an operator of that type.
2055-
auto representativeType = representativeDecl->getInterfaceType();
2056-
if (typesFound.count(representativeType.getPointer()))
2057-
continue;
2058-
typesFound.insert(representativeType.getPointer());
2042+
typesFound.insert(representativeDecl->getInterfaceType()->getCanonicalType());
2043+
}
20592044

2060-
for (auto *constraint : constraints) {
2061-
if (constraint->isFavored())
2062-
continue;
2063-
auto choice = constraint->getOverloadChoice();
2064-
if (choice.getDecl()->getInterfaceType()->isEqual(representativeType)) {
2065-
found.push_back(constraint);
2066-
break;
2067-
}
2068-
}
2069-
}
2045+
for (auto index : indices(constraints)) {
2046+
auto *constraint = constraints[index];
2047+
if (constraint->isFavored())
2048+
continue;
2049+
2050+
auto *decl = constraint->getOverloadChoice().getDecl();
2051+
if (typesFound.count(decl->getInterfaceType()->getCanonicalType()))
2052+
found.push_back(index);
20702053
}
20712054
}
20722055

20732056
void ConstraintSystem::partitionDisjunction(
20742057
ArrayRef<Constraint *> Choices, SmallVectorImpl<unsigned> &Ordering,
20752058
SmallVectorImpl<unsigned> &PartitionBeginning) {
20762059

2077-
SmallVector<Constraint *, 4> existing;
2078-
existingOperatorBindingsForDisjunction(*this, Choices, existing);
2079-
for (auto constraint : existing)
2080-
favorConstraint(constraint);
2081-
20822060
// Apply a special-case rule for favoring one generic function over
20832061
// another.
20842062
if (auto favored = tryOptimizeGenericDisjunction(DC, Choices)) {
@@ -2105,12 +2083,18 @@ void ConstraintSystem::partitionDisjunction(
21052083

21062084
// First collect some things that we'll generally put near the beginning or
21072085
// end of the partitioning.
2108-
21092086
SmallVector<unsigned, 4> favored;
2087+
SmallVector<unsigned, 4> everythingElse;
21102088
SmallVector<unsigned, 4> simdOperators;
21112089
SmallVector<unsigned, 4> disabled;
21122090
SmallVector<unsigned, 4> unavailable;
21132091

2092+
// Add existing operator bindings to the main partition first. This often
2093+
// helps the solver find a solution fast.
2094+
existingOperatorBindingsForDisjunction(*this, Choices, everythingElse);
2095+
for (auto index : everythingElse)
2096+
taken.insert(Choices[index]);
2097+
21142098
// First collect disabled and favored constraints.
21152099
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
21162100
if (constraint->isDisabled()) {
@@ -2170,7 +2154,6 @@ void ConstraintSystem::partitionDisjunction(
21702154
}
21712155
};
21722156

2173-
SmallVector<unsigned, 4> everythingElse;
21742157
// Gather the remaining options.
21752158
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
21762159
everythingElse.push_back(index);
@@ -2206,8 +2189,8 @@ Constraint *ConstraintSystem::selectDisjunction() {
22062189

22072190
if (firstFavored == secondFavored) {
22082191
// Look for additional choices to favor
2209-
SmallVector<Constraint *, 4> firstExisting;
2210-
SmallVector<Constraint *, 4> secondExisting;
2192+
SmallVector<unsigned, 4> firstExisting;
2193+
SmallVector<unsigned, 4> secondExisting;
22112194

22122195
existingOperatorBindingsForDisjunction(*cs, first->getNestedConstraints(), firstExisting);
22132196
firstFavored = firstExisting.size() ? firstExisting.size() : first->countActiveNestedConstraints();

0 commit comments

Comments
 (0)