14
14
15
15
#include " PMOMemoryUseCollector.h"
16
16
#include " swift/Basic/BlotSetVector.h"
17
+ #include " swift/Basic/FrozenMultiMap.h"
17
18
#include " swift/Basic/STLExtras.h"
18
19
#include " swift/SIL/BasicBlockUtils.h"
19
20
#include " swift/SIL/BranchPropagatedUser.h"
@@ -911,8 +912,10 @@ SILValue AvailableValueAggregator::handlePrimitiveValue(SILType loadTy,
911
912
return builder.emitCopyValueOperation (Loc, eltVal);
912
913
}
913
914
914
- static SILInstruction *getNonPhiBlockIncomingValueDef (SILValue incomingValue,
915
- CopyValueInst *phiCopy) {
915
+ static SILInstruction *
916
+ getNonPhiBlockIncomingValueDef (SILValue incomingValue,
917
+ SingleValueInstruction *phiCopy) {
918
+ assert (isa<CopyValueInst>(phiCopy));
916
919
auto *phiBlock = phiCopy->getParent ();
917
920
if (phiBlock == incomingValue->getParentBlock ()) {
918
921
return nullptr ;
@@ -962,7 +965,7 @@ class PhiNodeCopyCleanupInserter {
962
965
// / visit our incoming values in visitation order and that within
963
966
// / their own values, also visit them in visitation order with
964
967
// / respect to each other.
965
- SmallVector<std::pair< unsigned , CopyValueInst *> , 16 > copiesToCleanup;
968
+ SmallFrozenMultiMap< unsigned , SingleValueInstruction * , 16 > copiesToCleanup;
966
969
967
970
// / The lifetime frontier that we use to compute lifetime endpoints
968
971
// / when emitting cleanups.
@@ -976,7 +979,7 @@ class PhiNodeCopyCleanupInserter {
976
979
auto iter = incomingValues.insert (entry);
977
980
// If we did not succeed, then iter.first.second is the index of
978
981
// incoming value. Otherwise, it will be nextIndex.
979
- copiesToCleanup.emplace_back (iter.first ->second , copy);
982
+ copiesToCleanup.insert (iter.first ->second , copy);
980
983
}
981
984
982
985
void emit (DeadEndBlocks &deadEndBlocks) &&;
@@ -999,36 +1002,15 @@ void PhiNodeCopyCleanupInserter::emit(DeadEndBlocks &deadEndBlocks) && {
999
1002
// first phiNodeCleanupState for a specific phi, we process the phi
1000
1003
// then. This ensures that we always process the phis in insertion order as
1001
1004
// well.
1002
- SmallVector<unsigned , 32 > copiesToCleanupIndicesSorted;
1003
- llvm::copy (indices (copiesToCleanup),
1004
- std::back_inserter (copiesToCleanupIndicesSorted));
1005
-
1006
- stable_sort (copiesToCleanupIndicesSorted,
1007
- [&](unsigned lhsIndex, unsigned rhsIndex) {
1008
- unsigned lhs = copiesToCleanup[lhsIndex].first ;
1009
- unsigned rhs = copiesToCleanup[rhsIndex].first ;
1010
- return lhs < rhs;
1011
- });
1012
-
1013
- for (auto ii = copiesToCleanupIndicesSorted.begin (),
1014
- ie = copiesToCleanupIndicesSorted.end ();
1015
- ii != ie;) {
1016
- unsigned incomingValueIndex = copiesToCleanup[*ii].first ;
1017
-
1018
- // First find the end of the values for which ii does not equal baseValue.
1019
- auto rangeEnd = std::find_if_not (std::next (ii), ie, [&](unsigned index) {
1020
- return incomingValueIndex == copiesToCleanup[index].first ;
1021
- });
1005
+ copiesToCleanup.setFrozen ();
1022
1006
1023
- SWIFT_DEFER {
1024
- // Once we have finished processing, set ii to rangeEnd. This ensures that
1025
- // the code below does not need to worry about updating the iterator.
1026
- ii = rangeEnd;
1027
- };
1007
+ for (auto keyValue : copiesToCleanup.getRange ()) {
1008
+ unsigned incomingValueIndex = keyValue.first ;
1009
+ auto copies = keyValue.second ;
1028
1010
1029
1011
SILValue incomingValue =
1030
1012
std::next (incomingValues.begin (), incomingValueIndex)->first ;
1031
- CopyValueInst *phiCopy = copiesToCleanup[*ii]. second ;
1013
+ SingleValueInstruction *phiCopy = copies. front () ;
1032
1014
auto *insertPt = getNonPhiBlockIncomingValueDef (incomingValue, phiCopy);
1033
1015
auto loc = RegularLocation::getAutoGeneratedLocation ();
1034
1016
@@ -1038,8 +1020,7 @@ void PhiNodeCopyCleanupInserter::emit(DeadEndBlocks &deadEndBlocks) && {
1038
1020
// copy and continue. This means that
1039
1021
// cleanupState.getNonPhiBlockIncomingValueDef() should always return a
1040
1022
// non-null value in the code below.
1041
- if (std::next (ii) == rangeEnd && isa<SILArgument>(incomingValue) &&
1042
- !insertPt) {
1023
+ if (copies.size () == 1 && isa<SILArgument>(incomingValue) && !insertPt) {
1043
1024
SILBasicBlock *phiBlock = phiCopy->getParent ();
1044
1025
SILBuilderWithScope builder (phiBlock->getTerminator ());
1045
1026
builder.createDestroyValue (loc, incomingValue);
@@ -1048,17 +1029,12 @@ void PhiNodeCopyCleanupInserter::emit(DeadEndBlocks &deadEndBlocks) && {
1048
1029
1049
1030
// Otherwise, we know that we have for this incomingValue, multiple
1050
1031
// potential insert pts that we need to handle at the same time with our
1051
- // lifetime query. Gather up those uses.
1052
- SmallVector<SILInstruction *, 8 > users;
1053
- transform (llvm::make_range (ii, rangeEnd), std::back_inserter (users),
1054
- [&](unsigned index) { return copiesToCleanup[index].second ; });
1055
-
1056
- // Then lifetime extend our base over the copy_value.
1032
+ // lifetime query. Lifetime extend our base over these copy_value uses.
1057
1033
assert (lifetimeFrontier.empty ());
1058
1034
auto *def = getNonPhiBlockIncomingValueDef (incomingValue, phiCopy);
1059
1035
assert (def && " Should never have a nullptr here since we handled all of "
1060
1036
" the single block cases earlier" );
1061
- ValueLifetimeAnalysis analysis (def, users );
1037
+ ValueLifetimeAnalysis analysis (def, copies );
1062
1038
bool foundCriticalEdges = !analysis.computeFrontier (
1063
1039
lifetimeFrontier, ValueLifetimeAnalysis::DontModifyCFG, &deadEndBlocks);
1064
1040
(void )foundCriticalEdges;
0 commit comments