Skip to content

Commit 34fa9c2

Browse files
gregomnihborla
authored andcommitted
Merge typevars of operators with shared decls after finding a solution to speed up further searching
1 parent ab6d92b commit 34fa9c2

File tree

2 files changed

+77
-4
lines changed

2 files changed

+77
-4
lines changed

lib/Sema/CSStep.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,15 +659,50 @@ bool DisjunctionStep::shortCircuitDisjunctionAt(
659659
if (currentChoice->getKind() == ConstraintKind::CheckedCast)
660660
return true;
661661

662-
// If we have a SIMD operator, and the prior choice was not a SIMD
663-
// Operator, we're done.
662+
// Extra checks for binding of operators
664663
if (currentChoice->getKind() == ConstraintKind::BindOverload &&
665-
isSIMDOperator(currentChoice->getOverloadChoice().getDecl()) &&
664+
currentChoice->getOverloadChoice().getDecl()->isOperator() &&
666665
lastSuccessfulChoice->getKind() == ConstraintKind::BindOverload &&
667-
!isSIMDOperator(lastSuccessfulChoice->getOverloadChoice().getDecl())) {
666+
lastSuccessfulChoice->getOverloadChoice().getDecl()->isOperator()) {
668667
return true;
669668
}
670669

670+
// If we have a SIMD operator, and the prior choice was not a SIMD
671+
// Operator, we're done.
672+
if (isSIMDOperator(currentChoice->getOverloadChoice().getDecl()) &&
673+
!isSIMDOperator(lastSuccessfulChoice->getOverloadChoice().getDecl()))
674+
return true;
675+
676+
// Otherwise if we have an existing solution, bind tyvars bound to the same
677+
// decl in the solution to the choice tyvar. We can continue finding more
678+
// solutions, but all the instances of the operator that chose the same
679+
// overload as this successful choice will be bound togeter.
680+
if (Solutions.size()) {
681+
auto lastTyvar =
682+
lastSuccessfulChoice->getFirstType()->getAs<TypeVariableType>();
683+
auto lastRep = CS.getRepresentative(lastTyvar);
684+
685+
for (auto overload : Solutions[0].overloadChoices) {
686+
auto overloadChoice = overload.getSecond().choice;
687+
if (!overloadChoice.isDecl() ||
688+
overloadChoice.getDecl() !=
689+
lastSuccessfulChoice->getOverloadChoice().getDecl())
690+
continue;
691+
692+
auto choiceTyvar =
693+
CS.getType(simplifyLocatorToAnchor(CS, overload.getFirst()))
694+
->getAs<TypeVariableType>();
695+
if (!choiceTyvar)
696+
continue;
697+
698+
auto rep = CS.getRepresentative(choiceTyvar);
699+
if (lastRep != rep) {
700+
CS.mergeEquivalenceClasses(rep, lastRep);
701+
lastRep = CS.getRepresentative(lastRep);
702+
}
703+
}
704+
}
705+
}
671706
return false;
672707
}
673708

lib/Sema/CSStep.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ class DisjunctionStep final : public BindingStep<DisjunctionChoiceProducer> {
649649
: BindingStep(cs, {cs, disjunction}, solutions), Disjunction(disjunction),
650650
AfterDisjunction(erase(disjunction)) {
651651
assert(Disjunction->getKind() == ConstraintKind::Disjunction);
652+
pruneOverloadSet(Disjunction);
652653
++cs.solverState->NumDisjunctions;
653654
}
654655

@@ -696,6 +697,43 @@ class DisjunctionStep final : public BindingStep<DisjunctionChoiceProducer> {
696697
/// simplified further, false otherwise.
697698
bool attempt(const DisjunctionChoice &choice) override;
698699

700+
// Check if selected disjunction has a representative
701+
// this might happen when there are multiple binary operators
702+
// chained together. If so, disable choices which differ
703+
// from currently selected representative.
704+
void pruneOverloadSet(Constraint *disjunction) {
705+
auto *choice = disjunction->getNestedConstraints().front();
706+
auto *typeVar = choice->getFirstType()->getAs<TypeVariableType>();
707+
if (!typeVar)
708+
return;
709+
710+
auto *repr = typeVar->getImpl().getRepresentative(nullptr);
711+
if (!repr || repr == typeVar)
712+
return;
713+
714+
for (auto *resolved = getResolvedOverloads(); resolved;
715+
resolved = resolved->Previous) {
716+
if (!resolved->BoundType->isEqual(repr))
717+
continue;
718+
719+
auto &representative = resolved->Choice;
720+
if (!representative.isDecl())
721+
return;
722+
723+
// Disable all of the overload choices which are different from
724+
// the one which is currently picked for representative.
725+
for (auto *constraint : disjunction->getNestedConstraints()) {
726+
auto choice = constraint->getOverloadChoice();
727+
if (!choice.isDecl() || choice.getDecl() == representative.getDecl())
728+
continue;
729+
730+
constraint->setDisabled();
731+
DisabledChoices.push_back(constraint);
732+
}
733+
break;
734+
}
735+
};
736+
699737
// Figure out which of the solutions has the smallest score.
700738
static Optional<Score> getBestScore(SmallVectorImpl<Solution> &solutions) {
701739
assert(!solutions.empty());

0 commit comments

Comments
 (0)