Skip to content

Commit 29d8d20

Browse files
committed
[NFC] OSSACanOwned: Record defs in SmallVector.
In preparation for only recording the defs once, replace the GraphNodeWorklist of defs with a SetVector. Preserve the current visitation order by creating a worklist of indices to be visited.
1 parent 0089b62 commit 29d8d20

File tree

3 files changed

+40
-109
lines changed

3 files changed

+40
-109
lines changed

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 1 addition & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@
9696
#ifndef SWIFT_SILOPTIMIZER_UTILS_CANONICALOSSALIFETIME_H
9797
#define SWIFT_SILOPTIMIZER_UTILS_CANONICALOSSALIFETIME_H
9898

99-
#include "swift/Basic/GraphNodeWorklist.h"
10099
#include "swift/Basic/SmallPtrSetVector.h"
101100
#include "swift/Basic/TaggedUnion.h"
102101
#include "swift/SIL/PrunedLiveness.h"
@@ -342,12 +341,9 @@ class CanonicalizeOSSALifetime final {
342341
}
343342
};
344343
friend llvm::DenseMapInfo<Def>;
345-
friend llvm::PointerLikeTypeTraits<Def>;
346-
friend llvm::PointerLikeTypeTraits<
347-
std::optional<swift::CanonicalizeOSSALifetime::Def>>;
348344

349345
/// Visited set for general def-use traversal that prevents revisiting values.
350-
GraphNodeWorklist<std::optional<Def>, 8> defUseWorklist;
346+
SmallVector<Def, 8> defUseWorklist;
351347

352348
/// The blocks that were discovered by PrunedLiveness.
353349
SmallVector<SILBasicBlock *, 32> discoveredBlocks;
@@ -563,94 +559,4 @@ class CanonicalizeOSSALifetime final {
563559

564560
} // end namespace swift
565561

566-
namespace llvm {
567-
template <>
568-
struct DenseMapInfo<swift::CanonicalizeOSSALifetime::Def> {
569-
static swift::CanonicalizeOSSALifetime::Def getEmptyKey() {
570-
return swift::CanonicalizeOSSALifetime::Def::root(
571-
DenseMapInfo<swift::SILValue>::getEmptyKey());
572-
}
573-
static swift::CanonicalizeOSSALifetime::Def getTombstoneKey() {
574-
return swift::CanonicalizeOSSALifetime::Def::root(
575-
DenseMapInfo<swift::SILValue>::getTombstoneKey());
576-
}
577-
static unsigned getHashValue(swift::CanonicalizeOSSALifetime::Def def) {
578-
return detail::combineHashValue(
579-
DenseMapInfo<swift::CanonicalizeOSSALifetime::Def::Kind>::getHashValue(
580-
def.getKind()),
581-
DenseMapInfo<swift::SILValue>::getHashValue(def.getValue()));
582-
}
583-
static bool isEqual(swift::CanonicalizeOSSALifetime::Def LHS,
584-
swift::CanonicalizeOSSALifetime::Def RHS) {
585-
return LHS == RHS;
586-
}
587-
};
588-
template <>
589-
struct PointerLikeTypeTraits<swift::CanonicalizeOSSALifetime::Def> {
590-
private:
591-
using Def = swift::CanonicalizeOSSALifetime::Def;
592-
593-
public:
594-
static void *getAsVoidPointer(Def def) {
595-
return reinterpret_cast<void *>(
596-
reinterpret_cast<uintptr_t>(def.getValue().getOpaqueValue()) |
597-
((uintptr_t)def.getKind()) << NumLowBitsAvailable);
598-
}
599-
static Def getFromVoidPointer(void *p) {
600-
auto kind = (Def::Kind)((reinterpret_cast<uintptr_t>(p) & 0b110) >>
601-
NumLowBitsAvailable);
602-
auto opaque =
603-
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) & ~0b111);
604-
auto value = swift::SILValue::getFromOpaqueValue(opaque);
605-
switch (kind) {
606-
case Def::Kind::Root:
607-
return Def::root(value);
608-
case Def::Kind::Copy:
609-
return Def::copy(cast<swift::CopyValueInst>(value));
610-
case Def::Kind::Reborrow:
611-
return Def::reborrow(cast<swift::SILArgument>(value));
612-
case Def::Kind::BorrowedFrom:
613-
return Def::borrowedFrom(cast<swift::BorrowedFromInst>(value));
614-
}
615-
}
616-
617-
enum {
618-
NumLowBitsAvailable =
619-
llvm::PointerLikeTypeTraits<swift::SILValue>::NumLowBitsAvailable - 2
620-
};
621-
};
622-
template <>
623-
struct PointerLikeTypeTraits<
624-
std::optional<swift::CanonicalizeOSSALifetime::Def>> {
625-
private:
626-
using Def = swift::CanonicalizeOSSALifetime::Def;
627-
using Payload = std::optional<Def>;
628-
629-
public:
630-
static void *getAsVoidPointer(Payload payload) {
631-
if (!payload)
632-
return 0x0;
633-
return reinterpret_cast<void *>(
634-
reinterpret_cast<uintptr_t>(
635-
PointerLikeTypeTraits<swift::CanonicalizeOSSALifetime::Def>::
636-
getAsVoidPointer(*payload)) |
637-
0b1);
638-
}
639-
static Payload getFromVoidPointer(void *p) {
640-
auto none = reinterpret_cast<uintptr_t>(p) & 0b1;
641-
if (none)
642-
return std::nullopt;
643-
auto opaque =
644-
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) & ~0b1);
645-
return {PointerLikeTypeTraits<
646-
swift::CanonicalizeOSSALifetime::Def>::getFromVoidPointer(opaque)};
647-
}
648-
649-
enum {
650-
NumLowBitsAvailable =
651-
llvm::PointerLikeTypeTraits<Def>::NumLowBitsAvailable - 1
652-
};
653-
};
654-
} // end namespace llvm
655-
656562
#endif

lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableValuesChecker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/AST/DiagnosticsSIL.h"
1616
#include "swift/Basic/Assertions.h"
1717
#include "swift/Basic/Defer.h"
18+
#include "swift/Basic/GraphNodeWorklist.h"
1819
#include "swift/SIL/BasicBlockBits.h"
1920
#include "swift/SIL/BasicBlockDatastructures.h"
2021
#include "swift/SIL/DebugUtils.h"

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@
6565

6666
#define DEBUG_TYPE "copy-propagation"
6767

68-
#include "swift/Basic/Assertions.h"
6968
#include "swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h"
69+
#include "swift/Basic/Assertions.h"
7070
#include "swift/SIL/InstructionUtils.h"
7171
#include "swift/SIL/NodeDatastructures.h"
7272
#include "swift/SIL/OSSALifetimeCompletion.h"
@@ -132,18 +132,29 @@ static bool isDestroyOfCopyOf(SILInstruction *instruction, SILValue def) {
132132
bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
133133
LLVM_DEBUG(llvm::dbgs() << "Computing canonical liveness from:\n";
134134
getCurrentDef()->print(llvm::dbgs()));
135-
defUseWorklist.initialize(Def::root(getCurrentDef()));
135+
SmallVector<unsigned, 8> indexWorklist;
136+
ValueSet visitedDefs(getCurrentDef()->getFunction());
137+
auto addDefToWorklist = [&](Def def) {
138+
if (!visitedDefs.insert(def.getValue()))
139+
return;
140+
defUseWorklist.push_back(def);
141+
indexWorklist.push_back(defUseWorklist.size() - 1);
142+
};
143+
defUseWorklist.clear();
144+
addDefToWorklist(Def::root(getCurrentDef()));
136145
// Only the first level of reborrows need to be consider. All nested inner
137146
// adjacent reborrows and phis are encapsulated within their lifetimes.
138147
SILPhiArgument *arg;
139148
if ((arg = dyn_cast<SILPhiArgument>(getCurrentDef())) && arg->isPhi()) {
140149
visitInnerAdjacentPhis(arg, [&](SILArgument *reborrow) {
141-
defUseWorklist.insert(Def::reborrow(reborrow));
150+
addDefToWorklist(Def::reborrow(reborrow));
142151
return true;
143152
});
144153
}
145-
while (auto def = defUseWorklist.pop()) {
146-
auto value = def->getValue();
154+
while (!indexWorklist.empty()) {
155+
auto index = indexWorklist.pop_back_val();
156+
auto def = defUseWorklist[index];
157+
auto value = def.getValue();
147158
LLVM_DEBUG(llvm::dbgs() << " Uses of value:\n";
148159
value->print(llvm::dbgs()));
149160

@@ -154,11 +165,11 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
154165
auto *user = use->getUser();
155166
// Recurse through copies.
156167
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
157-
defUseWorklist.insert(Def::copy(copy));
168+
addDefToWorklist(Def::copy(copy));
158169
continue;
159170
}
160171
if (auto *bfi = dyn_cast<BorrowedFromInst>(user)) {
161-
defUseWorklist.insert(Def::borrowedFrom(bfi));
172+
addDefToWorklist(Def::borrowedFrom(bfi));
162173
continue;
163174
}
164175
// Handle debug_value instructions separately.
@@ -245,7 +256,7 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
245256
// This branch reborrows a guaranteed phi whose lifetime is dependent on
246257
// currentDef. Uses of the reborrowing phi extend liveness.
247258
auto *reborrow = PhiOperand(use).getValue();
248-
defUseWorklist.insert(Def::reborrow(reborrow));
259+
addDefToWorklist(Def::reborrow(reborrow));
249260
break;
250261
}
251262
}
@@ -1152,6 +1163,15 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11521163
// Shadow defUseWorklist in order to constrain its uses.
11531164
auto &defUseWorklist = this->defUseWorklist;
11541165

1166+
SmallVector<unsigned, 8> indexWorklist;
1167+
ValueSet visitedDefs(getCurrentDef()->getFunction());
1168+
auto addDefToWorklist = [&](Def def) {
1169+
if (!visitedDefs.insert(def.getValue()))
1170+
return;
1171+
defUseWorklist.push_back(def);
1172+
indexWorklist.push_back(defUseWorklist.size() - 1);
1173+
};
1174+
11551175
InstructionSetVector instsToDelete(getCurrentDef()->getFunction());
11561176

11571177
// Visit each operand in the def-use chain.
@@ -1162,7 +1182,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11621182
auto *user = use->getUser();
11631183
// Recurse through copies.
11641184
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
1165-
defUseWorklist.insert(Def::copy(copy));
1185+
addDefToWorklist(Def::copy(copy));
11661186
return true;
11671187
}
11681188
if (destroys.contains(user)) {
@@ -1197,18 +1217,22 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11971217
return true;
11981218
};
11991219

1200-
defUseWorklist.initialize(Def::root(getCurrentDef()));
1220+
defUseWorklist.clear();
1221+
addDefToWorklist(Def::root(getCurrentDef()));
12011222
// Perform a def-use traversal, visiting each use operand.
1202-
while (auto def = defUseWorklist.pop()) {
1203-
switch (*def) {
1223+
1224+
while (!indexWorklist.empty()) {
1225+
auto index = indexWorklist.pop_back_val();
1226+
auto def = defUseWorklist[index];
1227+
switch (def) {
12041228
case Def::Kind::BorrowedFrom:
12051229
case Def::Kind::Reborrow:
12061230
// Direct uses of these defs never need to be rewritten. Being guaranteed
12071231
// values, none of their direct uses consume an owned value.
12081232
assert(def.getValue()->getOwnershipKind() == OwnershipKind::Guaranteed);
12091233
break;
12101234
case Def::Kind::Root: {
1211-
SILValue value = def->getValue();
1235+
SILValue value = def.getValue();
12121236
for (auto useIter = value->use_begin(), endIter = value->use_end();
12131237
useIter != endIter;) {
12141238
Operand *use = *useIter++;
@@ -1219,7 +1243,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12191243
break;
12201244
}
12211245
case Def::Kind::Copy: {
1222-
SILValue value = def->getValue();
1246+
SILValue value = def.getValue();
12231247
CopyValueInst *srcCopy = cast<CopyValueInst>(value);
12241248
// Recurse through copies while replacing their uses.
12251249
Operand *reusedCopyOp = nullptr;

0 commit comments

Comments
 (0)