@@ -2015,7 +2015,9 @@ static Constraint *tryOptimizeGenericDisjunction(
2015
2015
2016
2016
// Performance hack: favor operator overloads with decl or type we're already
2017
2017
// 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) {
2019
2021
auto *choice = constraints.front ();
2020
2022
if (choice->getKind () != ConstraintKind::BindOverload)
2021
2023
return ;
@@ -2026,59 +2028,35 @@ static void existingOperatorBindingsForDisjunction(ConstraintSystem &CS, ArrayRe
2026
2028
auto decl = overload.getDecl ();
2027
2029
if (!decl->isOperator ())
2028
2030
return ;
2029
- auto baseName = decl->getBaseName ();
2030
-
2031
- SmallSet<TypeBase *, 8 > typesFound;
2032
2031
2032
+ SmallSet<CanType, 8 > typesFound;
2033
2033
for (auto overload : CS.getResolvedOverloads ()) {
2034
2034
auto resolved = overload.second ;
2035
2035
if (!resolved.choice .isDecl ())
2036
2036
continue ;
2037
- auto representativeDecl = resolved.choice .getDecl ();
2038
2037
2038
+ auto representativeDecl = resolved.choice .getDecl ();
2039
2039
if (!representativeDecl->isOperator ())
2040
2040
continue ;
2041
2041
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
+ }
2059
2044
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);
2070
2053
}
2071
2054
}
2072
2055
2073
2056
void ConstraintSystem::partitionDisjunction (
2074
2057
ArrayRef<Constraint *> Choices, SmallVectorImpl<unsigned > &Ordering,
2075
2058
SmallVectorImpl<unsigned > &PartitionBeginning) {
2076
2059
2077
- SmallVector<Constraint *, 4 > existing;
2078
- existingOperatorBindingsForDisjunction (*this , Choices, existing);
2079
- for (auto constraint : existing)
2080
- favorConstraint (constraint);
2081
-
2082
2060
// Apply a special-case rule for favoring one generic function over
2083
2061
// another.
2084
2062
if (auto favored = tryOptimizeGenericDisjunction (DC, Choices)) {
@@ -2105,12 +2083,18 @@ void ConstraintSystem::partitionDisjunction(
2105
2083
2106
2084
// First collect some things that we'll generally put near the beginning or
2107
2085
// end of the partitioning.
2108
-
2109
2086
SmallVector<unsigned , 4 > favored;
2087
+ SmallVector<unsigned , 4 > everythingElse;
2110
2088
SmallVector<unsigned , 4 > simdOperators;
2111
2089
SmallVector<unsigned , 4 > disabled;
2112
2090
SmallVector<unsigned , 4 > unavailable;
2113
2091
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
+
2114
2098
// First collect disabled and favored constraints.
2115
2099
forEachChoice (Choices, [&](unsigned index, Constraint *constraint) -> bool {
2116
2100
if (constraint->isDisabled ()) {
@@ -2170,7 +2154,6 @@ void ConstraintSystem::partitionDisjunction(
2170
2154
}
2171
2155
};
2172
2156
2173
- SmallVector<unsigned , 4 > everythingElse;
2174
2157
// Gather the remaining options.
2175
2158
forEachChoice (Choices, [&](unsigned index, Constraint *constraint) -> bool {
2176
2159
everythingElse.push_back (index);
@@ -2206,8 +2189,8 @@ Constraint *ConstraintSystem::selectDisjunction() {
2206
2189
2207
2190
if (firstFavored == secondFavored) {
2208
2191
// 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;
2211
2194
2212
2195
existingOperatorBindingsForDisjunction (*cs, first->getNestedConstraints (), firstExisting);
2213
2196
firstFavored = firstExisting.size () ? firstExisting.size () : first->countActiveNestedConstraints ();
0 commit comments