65
65
66
66
#define DEBUG_TYPE " copy-propagation"
67
67
68
- #include " swift/Basic/Assertions.h"
69
68
#include " swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h"
69
+ #include " swift/Basic/Assertions.h"
70
70
#include " swift/SIL/InstructionUtils.h"
71
71
#include " swift/SIL/NodeDatastructures.h"
72
72
#include " swift/SIL/OSSALifetimeCompletion.h"
@@ -132,18 +132,27 @@ static bool isDestroyOfCopyOf(SILInstruction *instruction, SILValue def) {
132
132
bool CanonicalizeOSSALifetime::computeCanonicalLiveness () {
133
133
LLVM_DEBUG (llvm::dbgs () << " Computing canonical liveness from:\n " ;
134
134
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 ()));
136
143
// Only the first level of reborrows need to be consider. All nested inner
137
144
// adjacent reborrows and phis are encapsulated within their lifetimes.
138
145
SILPhiArgument *arg;
139
146
if ((arg = dyn_cast<SILPhiArgument>(getCurrentDef ())) && arg->isPhi ()) {
140
147
visitInnerAdjacentPhis (arg, [&](SILArgument *reborrow) {
141
- defUseWorklist. insert (Def::reborrow (reborrow));
148
+ addDefToWorklist (Def::reborrow (reborrow));
142
149
return true ;
143
150
});
144
151
}
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 ();
147
156
LLVM_DEBUG (llvm::dbgs () << " Uses of value:\n " ;
148
157
value->print (llvm::dbgs ()));
149
158
@@ -154,11 +163,11 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
154
163
auto *user = use->getUser ();
155
164
// Recurse through copies.
156
165
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
157
- defUseWorklist. insert (Def::copy (copy));
166
+ addDefToWorklist (Def::copy (copy));
158
167
continue ;
159
168
}
160
169
if (auto *bfi = dyn_cast<BorrowedFromInst>(user)) {
161
- defUseWorklist. insert (Def::borrowedFrom (bfi));
170
+ addDefToWorklist (Def::borrowedFrom (bfi));
162
171
continue ;
163
172
}
164
173
// Handle debug_value instructions separately.
@@ -245,7 +254,7 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
245
254
// This branch reborrows a guaranteed phi whose lifetime is dependent on
246
255
// currentDef. Uses of the reborrowing phi extend liveness.
247
256
auto *reborrow = PhiOperand (use).getValue ();
248
- defUseWorklist. insert (Def::reborrow (reborrow));
257
+ addDefToWorklist (Def::reborrow (reborrow));
249
258
break ;
250
259
}
251
260
}
@@ -1152,6 +1161,13 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1152
1161
// Shadow defUseWorklist in order to constrain its uses.
1153
1162
auto &defUseWorklist = this ->defUseWorklist ;
1154
1163
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
+
1155
1171
InstructionSetVector instsToDelete (getCurrentDef ()->getFunction ());
1156
1172
1157
1173
// Visit each operand in the def-use chain.
@@ -1162,7 +1178,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1162
1178
auto *user = use->getUser ();
1163
1179
// Recurse through copies.
1164
1180
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
1165
- defUseWorklist. insert (Def::copy (copy));
1181
+ addDefToWorklist (Def::copy (copy));
1166
1182
return true ;
1167
1183
}
1168
1184
if (destroys.contains (user)) {
@@ -1197,18 +1213,22 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1197
1213
return true ;
1198
1214
};
1199
1215
1200
- defUseWorklist.initialize (Def::root (getCurrentDef ()));
1216
+ defUseWorklist.clear ();
1217
+ addDefToWorklist (Def::root (getCurrentDef ()));
1201
1218
// 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) {
1204
1224
case Def::Kind::BorrowedFrom:
1205
1225
case Def::Kind::Reborrow:
1206
1226
// Direct uses of these defs never need to be rewritten. Being guaranteed
1207
1227
// values, none of their direct uses consume an owned value.
1208
1228
assert (def.getValue ()->getOwnershipKind () == OwnershipKind::Guaranteed);
1209
1229
break ;
1210
1230
case Def::Kind::Root: {
1211
- SILValue value = def-> getValue ();
1231
+ SILValue value = def. getValue ();
1212
1232
for (auto useIter = value->use_begin (), endIter = value->use_end ();
1213
1233
useIter != endIter;) {
1214
1234
Operand *use = *useIter++;
@@ -1219,7 +1239,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1219
1239
break ;
1220
1240
}
1221
1241
case Def::Kind::Copy: {
1222
- SILValue value = def-> getValue ();
1242
+ SILValue value = def. getValue ();
1223
1243
CopyValueInst *srcCopy = cast<CopyValueInst>(value);
1224
1244
// Recurse through copies while replacing their uses.
1225
1245
Operand *reusedCopyOp = nullptr ;
0 commit comments