Skip to content

Commit c95e185

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

File tree

3 files changed

+36
-85
lines changed

3 files changed

+36
-85
lines changed

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 1 addition & 71 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+
llvm::SmallSetVector<Def, 8> defUseWorklist;
351347

352348
/// The blocks that were discovered by PrunedLiveness.
353349
SmallVector<SILBasicBlock *, 32> discoveredBlocks;
@@ -585,72 +581,6 @@ struct DenseMapInfo<swift::CanonicalizeOSSALifetime::Def> {
585581
return LHS == RHS;
586582
}
587583
};
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-
};
654584
} // end namespace llvm
655585

656586
#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: 34 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,27 @@ 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+
auto addDefToWorklist = [&](Def def) {
137+
if (!defUseWorklist.insert(def))
138+
return;
139+
indexWorklist.push_back(defUseWorklist.size() - 1);
140+
};
141+
defUseWorklist.clear();
142+
addDefToWorklist(Def::root(getCurrentDef()));
136143
// Only the first level of reborrows need to be consider. All nested inner
137144
// adjacent reborrows and phis are encapsulated within their lifetimes.
138145
SILPhiArgument *arg;
139146
if ((arg = dyn_cast<SILPhiArgument>(getCurrentDef())) && arg->isPhi()) {
140147
visitInnerAdjacentPhis(arg, [&](SILArgument *reborrow) {
141-
defUseWorklist.insert(Def::reborrow(reborrow));
148+
addDefToWorklist(Def::reborrow(reborrow));
142149
return true;
143150
});
144151
}
145-
while (auto def = defUseWorklist.pop()) {
146-
auto value = def->getValue();
152+
while (!indexWorklist.empty()) {
153+
auto index = indexWorklist.pop_back_val();
154+
auto def = defUseWorklist[index];
155+
auto value = def.getValue();
147156
LLVM_DEBUG(llvm::dbgs() << " Uses of value:\n";
148157
value->print(llvm::dbgs()));
149158

@@ -154,11 +163,11 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
154163
auto *user = use->getUser();
155164
// Recurse through copies.
156165
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
157-
defUseWorklist.insert(Def::copy(copy));
166+
addDefToWorklist(Def::copy(copy));
158167
continue;
159168
}
160169
if (auto *bfi = dyn_cast<BorrowedFromInst>(user)) {
161-
defUseWorklist.insert(Def::borrowedFrom(bfi));
170+
addDefToWorklist(Def::borrowedFrom(bfi));
162171
continue;
163172
}
164173
// Handle debug_value instructions separately.
@@ -245,7 +254,7 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
245254
// This branch reborrows a guaranteed phi whose lifetime is dependent on
246255
// currentDef. Uses of the reborrowing phi extend liveness.
247256
auto *reborrow = PhiOperand(use).getValue();
248-
defUseWorklist.insert(Def::reborrow(reborrow));
257+
addDefToWorklist(Def::reborrow(reborrow));
249258
break;
250259
}
251260
}
@@ -1152,6 +1161,13 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11521161
// Shadow defUseWorklist in order to constrain its uses.
11531162
auto &defUseWorklist = this->defUseWorklist;
11541163

1164+
SmallVector<unsigned, 8> indexWorklist;
1165+
auto addDefToWorklist = [&](Def def) {
1166+
if (!defUseWorklist.insert(def))
1167+
return;
1168+
indexWorklist.push_back(defUseWorklist.size() - 1);
1169+
};
1170+
11551171
InstructionSetVector instsToDelete(getCurrentDef()->getFunction());
11561172

11571173
// Visit each operand in the def-use chain.
@@ -1162,7 +1178,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11621178
auto *user = use->getUser();
11631179
// Recurse through copies.
11641180
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
1165-
defUseWorklist.insert(Def::copy(copy));
1181+
addDefToWorklist(Def::copy(copy));
11661182
return true;
11671183
}
11681184
if (destroys.contains(user)) {
@@ -1197,18 +1213,22 @@ void CanonicalizeOSSALifetime::rewriteCopies(
11971213
return true;
11981214
};
11991215

1200-
defUseWorklist.initialize(Def::root(getCurrentDef()));
1216+
defUseWorklist.clear();
1217+
addDefToWorklist(Def::root(getCurrentDef()));
12011218
// Perform a def-use traversal, visiting each use operand.
1202-
while (auto def = defUseWorklist.pop()) {
1203-
switch (*def) {
1219+
1220+
while (!indexWorklist.empty()) {
1221+
auto index = indexWorklist.pop_back_val();
1222+
auto def = defUseWorklist[index];
1223+
switch (def) {
12041224
case Def::Kind::BorrowedFrom:
12051225
case Def::Kind::Reborrow:
12061226
// Direct uses of these defs never need to be rewritten. Being guaranteed
12071227
// values, none of their direct uses consume an owned value.
12081228
assert(def.getValue()->getOwnershipKind() == OwnershipKind::Guaranteed);
12091229
break;
12101230
case Def::Kind::Root: {
1211-
SILValue value = def->getValue();
1231+
SILValue value = def.getValue();
12121232
for (auto useIter = value->use_begin(), endIter = value->use_end();
12131233
useIter != endIter;) {
12141234
Operand *use = *useIter++;
@@ -1219,7 +1239,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
12191239
break;
12201240
}
12211241
case Def::Kind::Copy: {
1222-
SILValue value = def->getValue();
1242+
SILValue value = def.getValue();
12231243
CopyValueInst *srcCopy = cast<CopyValueInst>(value);
12241244
// Recurse through copies while replacing their uses.
12251245
Operand *reusedCopyOp = nullptr;

0 commit comments

Comments
 (0)