Skip to content

Commit 5722984

Browse files
committed
Rewrite flattening to be more effective with nested products
1 parent ce68627 commit 5722984

File tree

3 files changed

+85
-38
lines changed

3 files changed

+85
-38
lines changed

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 82 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -623,23 +623,23 @@ namespace {
623623
}
624624
}
625625

626-
void show(llvm::raw_ostream &buffer, bool normalize = true) const {
626+
void show(llvm::raw_ostream &buffer, bool forDisplay = true) const {
627627
switch (getKind()) {
628628
case SpaceKind::Empty:
629-
if (normalize) {
629+
if (forDisplay) {
630630
buffer << "_";
631631
} else {
632632
buffer << "[EMPTY]";
633633
}
634634
break;
635635
case SpaceKind::Disjunct: {
636-
if (normalize) {
636+
if (forDisplay) {
637637
assert(false && "Attempted to display disjunct to user!");
638638
} else {
639639
buffer << "DISJOIN(";
640640
for (auto &sp : Spaces) {
641641
buffer << "\n";
642-
sp.show(buffer, normalize);
642+
sp.show(buffer, forDisplay);
643643
buffer << " |";
644644
}
645645
buffer << ")";
@@ -665,7 +665,7 @@ namespace {
665665
if (!first) {
666666
buffer << ", ";
667667
}
668-
param.show(buffer, normalize);
668+
param.show(buffer, forDisplay);
669669
if (first) {
670670
first = false;
671671
}
@@ -674,7 +674,7 @@ namespace {
674674
}
675675
break;
676676
case SpaceKind::Type:
677-
if (!normalize) {
677+
if (!forDisplay) {
678678
getType()->print(buffer);
679679
}
680680
buffer << "_";
@@ -937,9 +937,6 @@ namespace {
937937
for (auto &uncoveredSpace : uncovered.getSpaces()) {
938938
SmallVector<Space, 4> flats;
939939
flatten(uncoveredSpace, flats);
940-
if (flats.empty()) {
941-
flats.append({ uncoveredSpace });
942-
}
943940
for (auto &flat : flats) {
944941
OS << tok::kw_case << " ";
945942
flat.show(OS);
@@ -956,9 +953,6 @@ namespace {
956953
for (auto &uncoveredSpace : uncovered.getSpaces()) {
957954
SmallVector<Space, 4> flats;
958955
flatten(uncoveredSpace, flats);
959-
if (flats.empty()) {
960-
flats.append({ uncoveredSpace });
961-
}
962956
for (auto &flat : flats) {
963957
Buffer.clear();
964958
flat.show(OS);
@@ -972,39 +966,91 @@ namespace {
972966
private:
973967
// Recursively unpacks a space of disjunctions or constructor parameters
974968
// into its component parts such that the resulting array of flattened
975-
// spaces contains no further disjunctions. If there were no disjunctions
976-
// in the starting space, the original space is already flat and the
977-
// returned array of spaces will be empty.
969+
// spaces contains no further disjunctions. The resulting flattened array
970+
// will never be empty.
978971
static void flatten(const Space space, SmallVectorImpl<Space> &flats) {
979972
switch (space.getKind()) {
980973
case SpaceKind::Constructor: {
981-
size_t i = 0;
982-
for (auto &param : space.getSpaces()) {
983-
// We're only interested in recursively unpacking constructors and
984-
// disjunctions (booleans are considered constructors).
985-
if (param.getKind() != SpaceKind::Constructor
986-
|| param.getKind() != SpaceKind::Disjunct
987-
|| param.getKind() != SpaceKind::BooleanConstant)
988-
continue;
974+
// Optimization: If this space is just a constructor head, it is already
975+
// flat.
976+
if (space.getSpaces().empty()) {
977+
flats.push_back(space);
978+
return;
979+
}
980+
981+
// To recursively recover a pattern matrix from a bunch of disjuncts:
982+
// 1) Unpack the arguments to the constructor under scrutiny.
983+
// 2) Traverse each argument in turn.
984+
// 3) Flatten the argument space into a column vector.
985+
// 4) Extend the existing pattern matrix by a factor of the size of
986+
// the column vector and copy each previous component.
987+
// 5) Extend the expanded matrix with multiples of the column vector's
988+
// components until filled.
989+
// 6) Wrap each matrix row in the constructor under scrutiny.
990+
size_t multiplier = 1;
991+
SmallVector<SmallVector<Space, 4>, 2> matrix;
992+
for (auto &subspace : space.getSpaces()) {
993+
SmallVector<Space, 4> columnVect;
994+
flatten(subspace, columnVect);
995+
996+
// Pattern matrices grow quasi-factorially in the size of the
997+
// input space.
998+
multiplier *= columnVect.size();
999+
1000+
size_t startSize = matrix.size();
1001+
if (!matrix.empty() && columnVect.size() > 1) {
1002+
size_t oldCount = matrix.size();
1003+
matrix.reserve(multiplier * oldCount);
1004+
// Indexing starts at 1, we already have 'startSize'-many elements
1005+
// in the matrix; multiplies by 1 are no-ops.
1006+
for (size_t i = 1; i < multiplier; ++i) {
1007+
std::copy_n(matrix.begin(), oldCount, std::back_inserter(matrix));
1008+
}
1009+
}
1010+
1011+
if (matrix.empty()) {
1012+
// Get the empty matrix setup with its starting row vectors.
1013+
for (auto &vspace : columnVect) {
1014+
matrix.push_back({});
1015+
matrix.back().push_back(vspace);
1016+
}
1017+
} else {
1018+
// Given a matrix of 'n' rows and '(m-1)*k' columns, to make a
1019+
// matrix of size 'n' by 'm*k' we need to copy each element of the
1020+
// column vector into a row 'm' times - as many times as there were
1021+
// elements of the original matrix before multiplication.
1022+
size_t stride = multiplier;
1023+
if (startSize == 1) {
1024+
// Special case: If the column vector is bigger than the matrix
1025+
// before multiplication, we need to index it linearly
1026+
stride = 1;
1027+
} else if (columnVect.size() == 1) {
1028+
// Special case: If the column vector has size 1 then we needn't
1029+
// stride at all.
1030+
stride = matrix.size();
1031+
}
1032+
1033+
for (size_t rowIdx = 0, colIdx = 0; rowIdx < matrix.size(); ++rowIdx) {
1034+
if (rowIdx != 0 && (rowIdx % stride) == 0) {
1035+
colIdx++;
1036+
}
9891037

990-
SmallVector<Space, 4> flattenedParams;
991-
flatten(param, flattenedParams);
992-
for (auto &space : flattenedParams) {
993-
SmallVector<Space, 4> row(space.getSpaces().begin(),
994-
space.getSpaces().end());
995-
row[i] = space;
996-
Space cs(space.getType(), space.getHead(), row);
997-
flats.push_back(cs);
1038+
matrix[rowIdx].push_back(columnVect[colIdx]);
1039+
}
9981040
}
999-
++i;
1041+
}
1042+
1043+
// Wrap the matrix rows into this constructor.
1044+
for (auto &row : matrix) {
1045+
flats.push_back(Space(space.getType(), space.getHead(), row));
10001046
}
10011047
}
10021048
break;
10031049
case SpaceKind::Disjunct: {
1004-
auto begin = space.getSpaces().begin();
1005-
auto end = space.getSpaces().end();
1006-
for (; begin != end; ++begin) {
1007-
flatten(*begin, flats);
1050+
for (auto &subspace : space.getSpaces()) {
1051+
SmallVector<Space, 4> buf;
1052+
flatten(subspace, buf);
1053+
flats.append(buf.begin(), buf.end());
10081054
}
10091055
}
10101056
break;
@@ -1114,5 +1160,4 @@ void SpaceEngine::Space::dump() const {
11141160
llvm::raw_svector_ostream os(buf);
11151161
this->show(os, /*normalize*/false);
11161162
llvm::errs() << buf.str();
1117-
llvm::errs() << "\n";
11181163
}

test/NameBinding/reference-dependencies.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ func lookUpManyTopLevelNames() {
215215
switch getOtherFileEnum() {
216216
case .Value:
217217
break
218+
default:
219+
break
218220
}
219221

220222
_ = .Value as OtherFileEnumWrapper.Enum

validation-test/Driver/Dependencies/rdar25405605.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
// RUN: cp %S/Inputs/rdar25405605/helper-3.swift %t/helper.swift
6060
// RUN: touch -t 201401240007 %t/helper.swift
61-
// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar25405605/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-3 %s
61+
// RUN: cd %t && not %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar25405605/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-3 %s
6262

6363
// CHECK-3-NOT: warning
6464
// CHECK-3: {{^{$}}

0 commit comments

Comments
 (0)