Skip to content

[Perf Experiment][ConstraintGraph] Gather constraints improvements #18281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "ConstraintGraph.h"
#include "ConstraintSystem.h"
#include "llvm/ADT/SetVector.h"
#include <tuple>

using namespace swift;
Expand Down Expand Up @@ -361,8 +362,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type");

// Gather the constraints associated with this type variable.
SmallVector<Constraint *, 8> constraints;
llvm::SmallPtrSet<Constraint *, 4> visitedConstraints;
llvm::SetVector<Constraint *> constraints;
getConstraintGraph().gatherConstraints(
typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);

Expand All @@ -377,10 +377,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
bool hasNonDependentMemberRelationalConstraints = false;
bool hasDependentMemberRelationalConstraints = false;
for (auto constraint : constraints) {
// Only visit each constraint once.
if (!visitedConstraints.insert(constraint).second)
continue;

switch (constraint->getKind()) {
case ConstraintKind::Bind:
case ConstraintKind::Equal:
Expand Down
39 changes: 19 additions & 20 deletions lib/Sema/CSDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "swift/Basic/Defer.h"
#include "swift/Basic/StringExtras.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"

Expand Down Expand Up @@ -8727,29 +8728,27 @@ bool FailureDiagnosis::diagnoseArchetypeAmbiguity() {
// because type B would have no constraints associated with it.
unsigned numConstraints = 0;
{
llvm::SmallVector<Constraint *, 2> constraints;
llvm::SetVector<Constraint *> constraints;
CS.getConstraintGraph().gatherConstraints(
tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);

for (auto constraint : constraints) {
// We are not interested in ConformsTo constraints because
// such constraints specify restrictions on the archetypes themselves.
if (constraint->getKind() == ConstraintKind::ConformsTo)
continue;
tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
[&](Constraint *constraint) -> bool {
// We are not interested in ConformsTo constraints because
// we can't derive any concrete type information from them.
if (constraint->getKind() == ConstraintKind::ConformsTo)
return false;

if (constraint->getKind() == ConstraintKind::Bind) {
if (auto locator = constraint->getLocator()) {
auto anchor = locator->getAnchor();
if (anchor && isa<UnresolvedDotExpr>(anchor))
return false;
}
}

// Some of the bind constraints specify relations between
// parent type and it's member fields/types, we are not
// interested in that, since it's not related to archetype resolution.
if (constraint->getKind() == ConstraintKind::Bind) {
if (auto locator = constraint->getLocator()) {
auto anchor = locator->getAnchor();
if (anchor && isa<UnresolvedDotExpr>(anchor))
continue;
}
}
return true;
});

numConstraints++;
}
numConstraints = constraints.size();
}

auto locator = impl.getLocator();
Expand Down
24 changes: 13 additions & 11 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "swift/AST/SubstitutionMap.h"
#include "swift/Sema/IDETypeChecking.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include <utility>
Expand Down Expand Up @@ -574,18 +575,19 @@ namespace {
// being applied, and the only constraint attached to it should
// be the disjunction constraint for the overload group.
auto &CG = CS.getConstraintGraph();
SmallVector<Constraint *, 4> constraints;
CG.gatherConstraints(tyvarType, constraints,
ConstraintGraph::GatheringKind::EquivalenceClass);
if (constraints.empty())
llvm::SetVector<Constraint *> disjunctions;
CG.gatherConstraints(tyvarType, disjunctions,
ConstraintGraph::GatheringKind::EquivalenceClass,
[](Constraint *constraint) -> bool {
return constraint->getKind() ==
ConstraintKind::Disjunction;
});
if (disjunctions.empty())
return;

// Look for the disjunction that binds the overload set.
for (auto constraint : constraints) {
if (constraint->getKind() != ConstraintKind::Disjunction)
continue;

auto oldConstraints = constraint->getNestedConstraints();
for (auto *disjunction : disjunctions) {
auto oldConstraints = disjunction->getNestedConstraints();
auto csLoc = CS.getConstraintLocator(expr->getFn());

// Only replace the disjunctive overload constraint.
Expand Down Expand Up @@ -633,8 +635,8 @@ namespace {

// Remove the original constraint from the inactive constraint
// list and add the new one.
CS.removeInactiveConstraint(constraint);
CS.removeInactiveConstraint(disjunction);

// Create the disjunction of favored constraints.
auto favoredConstraintsDisjunction =
Constraint::createDisjunction(CS,
Expand Down
23 changes: 13 additions & 10 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/StringExtras.h"
#include "swift/ClangImporter/ClangModule.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Compiler.h"

using namespace swift;
Expand Down Expand Up @@ -5049,17 +5050,19 @@ ConstraintSystem::addKeyPathApplicationRootConstraint(Type root, ConstraintLocat
auto typeVar = getType(keyPathExpr)->getAs<TypeVariableType>();
if (!typeVar)
return;

SmallVector<Constraint *, 4> constraints;
CG.gatherConstraints(typeVar, constraints,
ConstraintGraph::GatheringKind::EquivalenceClass);


llvm::SetVector<Constraint *> constraints;
CG.gatherConstraints(
typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
[&keyPathExpr](Constraint *constraint) -> bool {
return constraint->getKind() == ConstraintKind::KeyPath &&
constraint->getLocator()->getAnchor() == keyPathExpr;
});

for (auto constraint : constraints) {
if (constraint->getKind() == ConstraintKind::KeyPath &&
constraint->getLocator()->getAnchor() == keyPathExpr) {
auto keyPathRootTy = constraint->getSecondType();
addConstraint(ConstraintKind::Subtype, root->getWithoutSpecifierType(), keyPathRootTy, locator);
}
auto keyPathRootTy = constraint->getSecondType();
addConstraint(ConstraintKind::Subtype, root->getWithoutSpecifierType(),
keyPathRootTy, locator);
}
}

Expand Down
61 changes: 31 additions & 30 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ConstraintSystem.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/TypeWalker.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"
Expand Down Expand Up @@ -93,15 +94,18 @@ Optional<Type> ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar,
*isNilLiteral = false;

// Look for a literal-conformance constraint on the type variable.
SmallVector<Constraint *, 8> constraints;
llvm::SetVector<Constraint *> constraints;
getConstraintGraph().gatherConstraints(
bindingTypeVar, constraints,
ConstraintGraph::GatheringKind::EquivalenceClass);
ConstraintGraph::GatheringKind::EquivalenceClass,
[](Constraint *constraint) -> bool {
return constraint->getKind() == ConstraintKind::LiteralConformsTo &&
constraint->getProtocol()->isSpecificProtocol(
KnownProtocolKind::ExpressibleByNilLiteral);
});

for (auto constraint : constraints) {
if (constraint->getKind() == ConstraintKind::LiteralConformsTo &&
constraint->getProtocol()->isSpecificProtocol(
KnownProtocolKind::ExpressibleByNilLiteral) &&
simplifyType(constraint->getFirstType())->isEqual(bindingTypeVar)) {
if (simplifyType(constraint->getFirstType())->isEqual(bindingTypeVar)) {
*isNilLiteral = true;
break;
}
Expand Down Expand Up @@ -1914,14 +1918,14 @@ static Constraint *selectBestBindingDisjunction(
->getAs<TypeVariableType>();
assert(tv);

SmallVector<Constraint *, 8> constraints;
llvm::SetVector<Constraint *> constraints;
cs.getConstraintGraph().gatherConstraints(
tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);
tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
[](Constraint *constraint) {
return constraint->getKind() == ConstraintKind::Conversion;
});

for (auto *constraint : constraints) {
if (constraint->getKind() != ConstraintKind::Conversion)
continue;

auto toType =
cs.simplifyType(constraint->getSecondType())->getRValueType();
auto *toTV = toType->getAs<TypeVariableType>();
Expand Down Expand Up @@ -2244,26 +2248,23 @@ void DisjunctionChoice::propagateConversionInfo() const {
return;

auto conversionType = bindings.Bindings[0].BindingType;
SmallVector<Constraint *, 4> constraints;
llvm::SetVector<Constraint *> constraints;
CS->CG.gatherConstraints(typeVar, constraints,
ConstraintGraph::GatheringKind::EquivalenceClass);

bool viableForBinding = true;
for (auto adjacent : constraints) {
switch (adjacent->getKind()) {
case ConstraintKind::Conversion:
case ConstraintKind::Defaultable:
case ConstraintKind::ConformsTo:
case ConstraintKind::LiteralConformsTo:
break;

default:
viableForBinding = false;
break;
}
}

if (viableForBinding)
ConstraintGraph::GatheringKind::EquivalenceClass,
[](Constraint *constraint) -> bool {
switch (constraint->getKind()) {
case ConstraintKind::Conversion:
case ConstraintKind::Defaultable:
case ConstraintKind::ConformsTo:
case ConstraintKind::LiteralConformsTo:
return false;

default:
return true;
}
});

if (constraints.empty())
CS->addConstraint(ConstraintKind::Bind, typeVar, conversionType,
Choice->getLocator());
}
19 changes: 12 additions & 7 deletions lib/Sema/ConstraintGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "ConstraintGraphScope.h"
#include "ConstraintSystem.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SaveAndRestore.h"
#include <algorithm>
Expand Down Expand Up @@ -467,18 +468,20 @@ void ConstraintGraph::unbindTypeVariable(TypeVariableType *typeVar, Type fixed){
}

void ConstraintGraph::gatherConstraints(
TypeVariableType *typeVar,
SmallVectorImpl<Constraint *> &constraints,
GatheringKind kind) {
TypeVariableType *typeVar, llvm::SetVector<Constraint *> &constraints,
GatheringKind kind,
llvm::function_ref<bool(Constraint *)> acceptConstraint) {
auto &reprNode = (*this)[CS.getRepresentative(typeVar)];
auto equivClass = reprNode.getEquivalenceClass();
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
for (auto typeVar : equivClass) {
if (!typeVars.insert(typeVar).second)
continue;

for (auto constraint : (*this)[typeVar].getConstraints())
constraints.push_back(constraint);
for (auto constraint : (*this)[typeVar].getConstraints()) {
if (acceptConstraint(constraint))
constraints.insert(constraint);
}

auto &node = (*this)[typeVar];

Expand Down Expand Up @@ -510,8 +513,10 @@ void ConstraintGraph::gatherConstraints(
if (!typeVars.insert(adjTypeVarEquiv).second)
continue;

for (auto constraint : (*this)[adjTypeVarEquiv].getConstraints())
constraints.push_back(constraint);
for (auto constraint : (*this)[adjTypeVarEquiv].getConstraints()) {
if (acceptConstraint(constraint))
constraints.insert(constraint);
}
}
}
}
Expand Down
12 changes: 7 additions & 5 deletions lib/Sema/ConstraintGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include <functional>
Expand Down Expand Up @@ -221,11 +222,12 @@ class ConstraintGraph {
/// Gather the set of constraints that involve the given type variable,
/// i.e., those constraints that will be affected when the type variable
/// gets merged or bound to a fixed type.
///
/// The resulting set of constraints may contain duplicates.
void gatherConstraints(TypeVariableType *typeVar,
SmallVectorImpl<Constraint *> &constraints,
GatheringKind kind);
void
gatherConstraints(TypeVariableType *typeVar,
llvm::SetVector<Constraint *> &constraints,
GatheringKind kind,
llvm::function_ref<bool(Constraint *)> acceptConstraint =
[](Constraint *constraint) { return true; });

/// Retrieve the type variables that correspond to nodes in the graph.
///
Expand Down
18 changes: 9 additions & 9 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "ConstraintGraph.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
Expand Down Expand Up @@ -213,17 +214,16 @@ void ConstraintSystem::setMustBeMaterializableRecursive(Type type)
void ConstraintSystem::addTypeVariableConstraintsToWorkList(
TypeVariableType *typeVar) {
// Gather the constraints affected by a change to this type variable.
SmallVector<Constraint *, 8> constraints;
CG.gatherConstraints(typeVar, constraints,
ConstraintGraph::GatheringKind::AllMentions);
llvm::SetVector<Constraint *> inactiveConstraints;
CG.gatherConstraints(
typeVar, inactiveConstraints, ConstraintGraph::GatheringKind::AllMentions,
[](Constraint *constraint) { return !constraint->isActive(); });

// Add any constraints that aren't already active to the worklist.
for (auto constraint : constraints) {
if (!constraint->isActive()) {
ActiveConstraints.splice(ActiveConstraints.end(),
InactiveConstraints, constraint);
constraint->setActive(true);
}
for (auto constraint : inactiveConstraints) {
ActiveConstraints.splice(ActiveConstraints.end(), InactiveConstraints,
constraint);
constraint->setActive(true);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// RUN: %scale-test --begin 7 --end 12 --step 1 --select incrementScopeCounter %s
// REQUIRES: OS=macosx
// REQUIRES: asserts
// REQUIRES: rdar42650365

let a = [[0]]
_ = a[0][0]
Expand Down