[Constraint solver] Don't remove/reintroduce disjunction when favoring.

When favoring particular constraints in a disjunction, don't remove
the old disjunction and create a new one---it's just churn in the
constraint system. Instead, favor the constraints that need it.

This technically flips the SR-139 test case from "too complex" to
being fast enough, but it's still fairly slow.
This commit is contained in:
Doug Gregor
2019-03-04 20:31:06 -08:00
parent 0f31416d96
commit daf4610be1
3 changed files with 30 additions and 45 deletions

View File

@@ -615,60 +615,45 @@ namespace {
if (!disjunction)
return;
auto oldConstraints = disjunction->getNestedConstraints();
auto csLoc = CS.getConstraintLocator(expr->getFn());
if (mustConsider) {
bool hasMustConsider = false;
for (auto oldConstraint : oldConstraints) {
auto overloadChoice = oldConstraint->getOverloadChoice();
if (overloadChoice.isDecl() &&
mustConsider(overloadChoice.getDecl()))
hasMustConsider = true;
}
if (hasMustConsider) {
// Find the favored constraints and mark them.
SmallVector<Constraint *, 4> newlyFavoredConstraints;
unsigned numFavoredConstraints = 0;
Constraint *firstFavored = nullptr;
for (auto constraint : disjunction->getNestedConstraints()) {
if (!constraint->getOverloadChoice().isDecl())
return;
}
}
auto decl = constraint->getOverloadChoice().getDecl();
if (mustConsider && mustConsider(decl)) {
// Roll back any constraints we favored.
for (auto favored : newlyFavoredConstraints)
favored->setFavored(false);
// Copy over the existing bindings, dividing the constraints up
// into "favored" and non-favored lists.
SmallVector<Constraint *, 4> favoredConstraints;
SmallVector<Constraint *, 4> fallbackConstraints;
for (auto oldConstraint : oldConstraints) {
if (!oldConstraint->getOverloadChoice().isDecl())
return;
auto decl = oldConstraint->getOverloadChoice().getDecl();
}
if (!decl->getAttrs().isUnavailable(CS.getASTContext()) &&
isFavored(decl)) {
favoredConstraints.push_back(oldConstraint);
oldConstraint->setFavored();
} else
fallbackConstraints.push_back(oldConstraint);
// If we might need to roll back the favored constraints, keep
// track of those we are favoring.
if (mustConsider && !constraint->isFavored())
newlyFavoredConstraints.push_back(constraint);
constraint->setFavored();
++numFavoredConstraints;
if (!firstFavored)
firstFavored = constraint;
}
}
// If we did not find any favored constraints, we're done.
if (favoredConstraints.empty()) return;
if (favoredConstraints.size() == 1) {
auto overloadChoice = favoredConstraints[0]->getOverloadChoice();
// If there was one favored constraint, set the favored type based on its
// result type.
if (numFavoredConstraints == 1) {
auto overloadChoice = firstFavored->getOverloadChoice();
auto overloadType = overloadChoice.getDecl()->getInterfaceType();
auto resultType = overloadType->getAs<AnyFunctionType>()->getResult();
CS.setFavoredType(expr, resultType.getPointer());
}
// Remove the original constraint from the inactive constraint
// list and add the new one.
CS.removeInactiveConstraint(disjunction);
llvm::SmallVector<Constraint *, 2> aggregateConstraints;
aggregateConstraints.insert(aggregateConstraints.end(),
favoredConstraints.begin(),
favoredConstraints.end());
aggregateConstraints.insert(aggregateConstraints.end(),
fallbackConstraints.begin(),
fallbackConstraints.end());
CS.addDisjunctionConstraint(aggregateConstraints, csLoc);
}
size_t getOperandCount(Type t) {