@@ -1690,32 +1690,63 @@ void PatternMatchEmission::emitIsDispatch(ArrayRef<RowToSpecialize> rows,
1690
1690
1691
1691
namespace {
1692
1692
struct CaseInfo {
1693
- EnumElementDecl *FormalElement ;
1693
+ SmallVector<SpecializedRow, 2 > SpecializedRows ;
1694
1694
Pattern *FirstMatcher;
1695
1695
bool Irrefutable = false ;
1696
- SmallVector<SpecializedRow, 2 > SpecializedRows;
1696
+ };
1697
+
1698
+ class CaseBlocks {
1699
+ // These vectors are completely parallel, but the switch instructions want
1700
+ // only the first two, so we split them up.
1701
+ SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4 > CaseBBs;
1702
+ SmallVector<ProfileCounter, 4 > CaseCounts;
1703
+ SmallVector<CaseInfo, 4 > CaseInfos;
1704
+ SILBasicBlock *DefaultBB = nullptr ;
1705
+
1706
+ public:
1707
+ // / Create destination blocks for switching over the cases in an enum
1708
+ // / defined by \p rows.
1709
+ CaseBlocks (SILGenFunction &SGF,
1710
+ ArrayRef<RowToSpecialize> rows,
1711
+ CanType sourceType,
1712
+ SILBasicBlock *curBB);
1713
+
1714
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>>
1715
+ getCaseBlocks () const {
1716
+ return CaseBBs;
1717
+ }
1718
+
1719
+ ArrayRef<ProfileCounter> getCounts () const { return CaseCounts; }
1720
+
1721
+ SILBasicBlock *getDefaultBlock () const { return DefaultBB; }
1722
+
1723
+ void forEachCase (llvm::function_ref<void (EnumElementDecl *,
1724
+ SILBasicBlock *,
1725
+ const CaseInfo &)> op) const {
1726
+ for_each (CaseBBs, CaseInfos,
1727
+ [op](std::pair<EnumElementDecl *, SILBasicBlock *> casePair,
1728
+ const CaseInfo &info) {
1729
+ op (casePair.first , casePair.second , info);
1730
+ });
1731
+ }
1732
+
1733
+ bool hasAnyRefutableCase () const {
1734
+ return llvm::any_of (CaseInfos, [](const CaseInfo &info) {
1735
+ return !info.Irrefutable ;
1736
+ });
1737
+ }
1697
1738
};
1698
1739
} // end anonymous namespace
1699
1740
1700
- // / Create destination blocks for switching over the cases in an enum defined
1701
- // / by \p rows.
1702
- static void generateEnumCaseBlocks (
1741
+ CaseBlocks::CaseBlocks (
1703
1742
SILGenFunction &SGF,
1704
1743
ArrayRef<RowToSpecialize> rows,
1705
1744
CanType sourceType,
1706
- SILBasicBlock *curBB,
1707
- SmallVectorImpl<std::pair<EnumElementDecl *, SILBasicBlock *>> &caseBBs,
1708
- SmallVectorImpl<ProfileCounter> &caseCounts,
1709
- SmallVectorImpl<CaseInfo> &caseInfos,
1710
- SILBasicBlock *&defaultBB) {
1745
+ SILBasicBlock *curBB) {
1711
1746
1712
- assert (caseBBs.empty ());
1713
- assert (caseCounts.empty ());
1714
- assert (caseInfos.empty ());
1715
- assert (defaultBB == nullptr );
1716
-
1717
- caseBBs.reserve (rows.size ());
1718
- caseInfos.reserve (rows.size ());
1747
+ CaseBBs.reserve (rows.size ());
1748
+ CaseInfos.reserve (rows.size ());
1749
+ CaseCounts.reserve (rows.size ());
1719
1750
1720
1751
auto enumDecl = sourceType.getEnumOrBoundGenericEnum ();
1721
1752
@@ -1733,22 +1764,21 @@ static void generateEnumCaseBlocks(
1733
1764
}
1734
1765
assert (formalElt->getParentEnum () == enumDecl);
1735
1766
1736
- unsigned index = caseInfos .size ();
1767
+ unsigned index = CaseInfos .size ();
1737
1768
auto insertionResult = caseToIndex.insert ({formalElt, index});
1738
1769
if (!insertionResult.second ) {
1739
1770
index = insertionResult.first ->second ;
1740
1771
} else {
1741
1772
curBB = SGF.createBasicBlock (curBB);
1742
- caseBBs.push_back ({formalElt, curBB});
1743
- caseInfos.push_back (CaseInfo ());
1744
- caseInfos.back ().FormalElement = formalElt;
1745
- caseInfos.back ().FirstMatcher = row.Pattern ;
1746
- caseCounts.push_back (row.Count );
1773
+ CaseBBs.push_back ({formalElt, curBB});
1774
+ CaseInfos.push_back (CaseInfo ());
1775
+ CaseInfos.back ().FirstMatcher = row.Pattern ;
1776
+ CaseCounts.push_back (row.Count );
1747
1777
}
1748
1778
assert (caseToIndex[formalElt] == index);
1749
- assert (caseBBs [index].first == formalElt);
1779
+ assert (CaseBBs [index].first == formalElt);
1750
1780
1751
- auto &info = caseInfos [index];
1781
+ auto &info = CaseInfos [index];
1752
1782
info.Irrefutable = (info.Irrefutable || row.Irrefutable );
1753
1783
info.SpecializedRows .push_back (SpecializedRow ());
1754
1784
auto &specRow = info.SpecializedRows .back ();
@@ -1765,7 +1795,7 @@ static void generateEnumCaseBlocks(
1765
1795
}
1766
1796
}
1767
1797
1768
- assert (caseBBs .size () == caseInfos .size ());
1798
+ assert (CaseBBs .size () == CaseInfos .size ());
1769
1799
1770
1800
// Check to see if the enum may have values beyond the cases we can see
1771
1801
// at compile-time. This includes future cases (for resilient enums) and
@@ -1789,7 +1819,7 @@ static void generateEnumCaseBlocks(
1789
1819
}
1790
1820
1791
1821
if (!canAssumeExhaustive)
1792
- defaultBB = SGF.createBasicBlock (curBB);
1822
+ DefaultBB = SGF.createBasicBlock (curBB);
1793
1823
}
1794
1824
1795
1825
// / Perform specialized dispatch for a sequence of EnumElementPattern or an
@@ -1804,37 +1834,23 @@ void PatternMatchEmission::emitEnumElementDispatchWithOwnership(
1804
1834
CanType sourceType = rows[0 ].Pattern ->getType ()->getCanonicalType ();
1805
1835
1806
1836
// Collect the cases and specialized rows.
1807
- //
1808
- // These vectors are completely parallel, but the switch
1809
- // instructions want only the first information, so we split them up.
1810
- SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4 > caseBBs;
1811
- SmallVector<ProfileCounter, 4 > caseCounts;
1812
- SmallVector<CaseInfo, 4 > caseInfos;
1813
- SILBasicBlock *defaultBB = nullptr ;
1814
-
1815
- generateEnumCaseBlocks (SGF, rows, sourceType, SGF.B .getInsertionBB (),
1816
- caseBBs, caseCounts, caseInfos, defaultBB);
1837
+ CaseBlocks blocks{SGF, rows, sourceType, SGF.B .getInsertionBB ()};
1817
1838
1818
1839
SILLocation loc = PatternMatchStmt;
1819
1840
loc.setDebugLoc (rows[0 ].Pattern );
1820
1841
// SEMANTIC SIL TODO: Once we have the representation of a switch_enum that
1821
1842
// can take a +0 value, this extra copy should be a borrow.
1822
1843
SILValue srcValue = src.getFinalManagedValue ().copy (SGF, loc).forward (SGF);
1823
- // FIXME: Pass caseCounts in here as well, as it is in
1824
- // emitEnumElementDispatch.
1825
- ArrayRef<ProfileCounter> caseCountsArrayRef = caseCounts;
1826
- SGF.B .createSwitchEnum (loc, srcValue, defaultBB, caseBBs, caseCountsArrayRef,
1844
+ SGF.B .createSwitchEnum (loc, srcValue, blocks.getDefaultBlock (),
1845
+ blocks.getCaseBlocks (), blocks.getCounts (),
1827
1846
defaultCastCount);
1828
1847
1829
1848
// Okay, now emit all the cases.
1830
- for ( unsigned i = 0 , e = caseInfos. size (); i != e; ++i) {
1831
- auto &caseInfo = caseInfos[i];
1849
+ blocks. forEachCase ([&](EnumElementDecl *elt, SILBasicBlock *caseBB,
1850
+ const CaseInfo &caseInfo) {
1832
1851
SILLocation loc = caseInfo.FirstMatcher ;
1833
1852
auto &specializedRows = caseInfo.SpecializedRows ;
1834
1853
1835
- EnumElementDecl *elt = caseBBs[i].first ;
1836
- EnumElementDecl *formalElt = caseInfos[i].FormalElement ;
1837
- SILBasicBlock *caseBB = caseBBs[i].second ;
1838
1854
SGF.B .setInsertionPoint (caseBB);
1839
1855
1840
1856
// We're in conditionally-executed code; enter a scope.
@@ -1908,8 +1924,8 @@ void PatternMatchEmission::emitEnumElementDispatchWithOwnership(
1908
1924
1909
1925
CanType substEltTy =
1910
1926
sourceType
1911
- ->getTypeOfMember (SGF.SGM .M .getSwiftModule (), formalElt ,
1912
- formalElt ->getArgumentInterfaceType ())
1927
+ ->getTypeOfMember (SGF.SGM .M .getSwiftModule (), elt ,
1928
+ elt ->getArgumentInterfaceType ())
1913
1929
->getCanonicalType ();
1914
1930
1915
1931
AbstractionPattern origEltTy =
@@ -1923,10 +1939,10 @@ void PatternMatchEmission::emitEnumElementDispatchWithOwnership(
1923
1939
1924
1940
handleCase (eltCMV, specializedRows, outerFailure);
1925
1941
assert (!SGF.B .hasValidInsertionPoint () && " did not end block" );
1926
- }
1942
+ });
1927
1943
1928
1944
// Emit the default block if we needed one.
1929
- if (defaultBB) {
1945
+ if (SILBasicBlock * defaultBB = blocks. getDefaultBlock () ) {
1930
1946
SGF.B .setInsertionPoint (defaultBB);
1931
1947
SGF.B .createOwnedPHIArgument (src.getType ());
1932
1948
outerFailure (rows.back ().Pattern );
@@ -1949,16 +1965,7 @@ void PatternMatchEmission::emitEnumElementDispatch(
1949
1965
CanType sourceType = rows[0 ].Pattern ->getType ()->getCanonicalType ();
1950
1966
1951
1967
// Collect the cases and specialized rows.
1952
- //
1953
- // These vectors are completely parallel, but the switch
1954
- // instructions want only the first information, so we split them up.
1955
- SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 4 > caseBBs;
1956
- SmallVector<CaseInfo, 4 > caseInfos;
1957
- SmallVector<ProfileCounter, 4 > caseCounts;
1958
- SILBasicBlock *defaultBB = nullptr ;
1959
-
1960
- generateEnumCaseBlocks (SGF, rows, sourceType, SGF.B .getInsertionBB (),
1961
- caseBBs, caseCounts, caseInfos, defaultBB);
1968
+ CaseBlocks blocks{SGF, rows, sourceType, SGF.B .getInsertionBB ()};
1962
1969
1963
1970
// Emit the switch_enum{_addr} instruction.
1964
1971
bool addressOnlyEnum = src.getType ().isAddress ();
@@ -1977,12 +1984,9 @@ void PatternMatchEmission::emitEnumElementDispatch(
1977
1984
assert (!SGF.F .getModule ().getOptions ().EnableSILOwnership &&
1978
1985
" TakeOnSuccess is not supported when compiling with ownership" );
1979
1986
// If any of the specialization cases is refutable, we must copy.
1980
- for (auto caseInfo : caseInfos)
1981
- if (!caseInfo.Irrefutable )
1982
- goto refutable;
1983
- break ;
1987
+ if (!blocks.hasAnyRefutableCase ())
1988
+ break ;
1984
1989
1985
- refutable:
1986
1990
src = ConsumableManagedValue (ManagedValue::forUnmanaged (src.getValue ()),
1987
1991
CastConsumptionKind::CopyOnSuccess);
1988
1992
break ;
@@ -1992,24 +1996,22 @@ void PatternMatchEmission::emitEnumElementDispatch(
1992
1996
SILValue srcValue = src.getFinalManagedValue ().forward (SGF);
1993
1997
SILLocation loc = PatternMatchStmt;
1994
1998
loc.setDebugLoc (rows[0 ].Pattern );
1995
- ArrayRef<ProfileCounter> caseCountsArrayRef = caseCounts;
1996
1999
if (addressOnlyEnum) {
1997
- SGF.B .createSwitchEnumAddr (loc, srcValue, defaultBB, caseBBs,
1998
- caseCountsArrayRef, defaultCaseCount);
2000
+ SGF.B .createSwitchEnumAddr (loc, srcValue, blocks.getDefaultBlock (),
2001
+ blocks.getCaseBlocks (), blocks.getCounts (),
2002
+ defaultCaseCount);
1999
2003
} else {
2000
- SGF.B .createSwitchEnum (loc, srcValue, defaultBB, caseBBs,
2001
- caseCountsArrayRef, defaultCaseCount);
2004
+ SGF.B .createSwitchEnum (loc, srcValue, blocks.getDefaultBlock (),
2005
+ blocks.getCaseBlocks (), blocks.getCounts (),
2006
+ defaultCaseCount);
2002
2007
}
2003
2008
2004
2009
// Okay, now emit all the cases.
2005
- for ( unsigned i = 0 , e = caseInfos. size (); i != e; ++i) {
2006
- auto &caseInfo = caseInfos[i];
2010
+ blocks. forEachCase ([&](EnumElementDecl *elt, SILBasicBlock *caseBB,
2011
+ const CaseInfo &caseInfo) {
2007
2012
SILLocation loc = caseInfo.FirstMatcher ;
2008
2013
auto &specializedRows = caseInfo.SpecializedRows ;
2009
2014
2010
- EnumElementDecl *elt = caseBBs[i].first ;
2011
- EnumElementDecl *formalElt = caseInfos[i].FormalElement ;
2012
- SILBasicBlock *caseBB = caseBBs[i].second ;
2013
2015
SGF.B .setInsertionPoint (caseBB);
2014
2016
2015
2017
// We're in conditionally-executed code; enter a scope.
@@ -2131,8 +2133,8 @@ void PatternMatchEmission::emitEnumElementDispatch(
2131
2133
// Reabstract to the substituted type, if needed.
2132
2134
2133
2135
CanType substEltTy =
2134
- sourceType->getTypeOfMember (SGF.SGM .M .getSwiftModule (), formalElt ,
2135
- formalElt ->getArgumentInterfaceType ())
2136
+ sourceType->getTypeOfMember (SGF.SGM .M .getSwiftModule (), elt ,
2137
+ elt ->getArgumentInterfaceType ())
2136
2138
->getCanonicalType ();
2137
2139
2138
2140
AbstractionPattern origEltTy =
@@ -2155,10 +2157,10 @@ void PatternMatchEmission::emitEnumElementDispatch(
2155
2157
2156
2158
handleCase (eltCMV, specializedRows, *innerFailure);
2157
2159
assert (!SGF.B .hasValidInsertionPoint () && " did not end block" );
2158
- }
2160
+ });
2159
2161
2160
2162
// Emit the default block if we needed one.
2161
- if (defaultBB) {
2163
+ if (SILBasicBlock * defaultBB = blocks. getDefaultBlock () ) {
2162
2164
SGF.B .setInsertionPoint (defaultBB);
2163
2165
outerFailure (rows.back ().Pattern );
2164
2166
}
0 commit comments