Skip to content

Commit bf7ac27

Browse files
authored
Merge pull request #29896 from gottesmm/pr-0a06969f425624e1d9d39042fc499975eefdbdac
[sil] Use FrozenMultiMap in PredictableMemOpts instead of implementing the data structure by hand.
2 parents c14a51b + b44fbae commit bf7ac27

File tree

2 files changed

+24
-45
lines changed

2 files changed

+24
-45
lines changed

include/swift/SILOptimizer/Utils/ValueLifetime.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ class ValueLifetimeAnalysis {
3333
/// The lifetime frontier for the value. It is the list of instructions
3434
/// following the last uses of the value. All the frontier instructions
3535
/// end the value's lifetime.
36-
typedef llvm::SmallVector<SILInstruction *, 4> Frontier;
36+
using Frontier = SmallVector<SILInstruction *, 4>;
3737

38-
/// Constructor for the value \p Def with a specific set of users of Def's
39-
/// users.
40-
ValueLifetimeAnalysis(SILInstruction *def,
41-
ArrayRef<SILInstruction *> userList)
42-
: defValue(def), userSet(userList.begin(), userList.end()) {
38+
/// Constructor for the value \p Def with a specific range of users.
39+
///
40+
/// We templatize over the RangeTy so that we can initialize
41+
/// ValueLifetimeAnalysis with misc iterators including transform
42+
/// iterators.
43+
template <typename RangeTy>
44+
ValueLifetimeAnalysis(SILInstruction *def, const RangeTy &userRange)
45+
: defValue(def), userSet(userRange.begin(), userRange.end()) {
4346
propagateLiveness();
4447
}
4548

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "PMOMemoryUseCollector.h"
1616
#include "swift/Basic/BlotSetVector.h"
17+
#include "swift/Basic/FrozenMultiMap.h"
1718
#include "swift/Basic/STLExtras.h"
1819
#include "swift/SIL/BasicBlockUtils.h"
1920
#include "swift/SIL/BranchPropagatedUser.h"
@@ -911,8 +912,10 @@ SILValue AvailableValueAggregator::handlePrimitiveValue(SILType loadTy,
911912
return builder.emitCopyValueOperation(Loc, eltVal);
912913
}
913914

914-
static SILInstruction *getNonPhiBlockIncomingValueDef(SILValue incomingValue,
915-
CopyValueInst *phiCopy) {
915+
static SILInstruction *
916+
getNonPhiBlockIncomingValueDef(SILValue incomingValue,
917+
SingleValueInstruction *phiCopy) {
918+
assert(isa<CopyValueInst>(phiCopy));
916919
auto *phiBlock = phiCopy->getParent();
917920
if (phiBlock == incomingValue->getParentBlock()) {
918921
return nullptr;
@@ -962,7 +965,7 @@ class PhiNodeCopyCleanupInserter {
962965
/// visit our incoming values in visitation order and that within
963966
/// their own values, also visit them in visitation order with
964967
/// respect to each other.
965-
SmallVector<std::pair<unsigned, CopyValueInst *>, 16> copiesToCleanup;
968+
SmallFrozenMultiMap<unsigned, SingleValueInstruction *, 16> copiesToCleanup;
966969

967970
/// The lifetime frontier that we use to compute lifetime endpoints
968971
/// when emitting cleanups.
@@ -976,7 +979,7 @@ class PhiNodeCopyCleanupInserter {
976979
auto iter = incomingValues.insert(entry);
977980
// If we did not succeed, then iter.first.second is the index of
978981
// incoming value. Otherwise, it will be nextIndex.
979-
copiesToCleanup.emplace_back(iter.first->second, copy);
982+
copiesToCleanup.insert(iter.first->second, copy);
980983
}
981984

982985
void emit(DeadEndBlocks &deadEndBlocks) &&;
@@ -999,36 +1002,15 @@ void PhiNodeCopyCleanupInserter::emit(DeadEndBlocks &deadEndBlocks) && {
9991002
// first phiNodeCleanupState for a specific phi, we process the phi
10001003
// then. This ensures that we always process the phis in insertion order as
10011004
// 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();
10221006

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;
10281010

10291011
SILValue incomingValue =
10301012
std::next(incomingValues.begin(), incomingValueIndex)->first;
1031-
CopyValueInst *phiCopy = copiesToCleanup[*ii].second;
1013+
SingleValueInstruction *phiCopy = copies.front();
10321014
auto *insertPt = getNonPhiBlockIncomingValueDef(incomingValue, phiCopy);
10331015
auto loc = RegularLocation::getAutoGeneratedLocation();
10341016

@@ -1038,8 +1020,7 @@ void PhiNodeCopyCleanupInserter::emit(DeadEndBlocks &deadEndBlocks) && {
10381020
// copy and continue. This means that
10391021
// cleanupState.getNonPhiBlockIncomingValueDef() should always return a
10401022
// 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) {
10431024
SILBasicBlock *phiBlock = phiCopy->getParent();
10441025
SILBuilderWithScope builder(phiBlock->getTerminator());
10451026
builder.createDestroyValue(loc, incomingValue);
@@ -1048,17 +1029,12 @@ void PhiNodeCopyCleanupInserter::emit(DeadEndBlocks &deadEndBlocks) && {
10481029

10491030
// Otherwise, we know that we have for this incomingValue, multiple
10501031
// 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.
10571033
assert(lifetimeFrontier.empty());
10581034
auto *def = getNonPhiBlockIncomingValueDef(incomingValue, phiCopy);
10591035
assert(def && "Should never have a nullptr here since we handled all of "
10601036
"the single block cases earlier");
1061-
ValueLifetimeAnalysis analysis(def, users);
1037+
ValueLifetimeAnalysis analysis(def, copies);
10621038
bool foundCriticalEdges = !analysis.computeFrontier(
10631039
lifetimeFrontier, ValueLifetimeAnalysis::DontModifyCFG, &deadEndBlocks);
10641040
(void)foundCriticalEdges;

0 commit comments

Comments
 (0)