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,29 @@ 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
+ 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 ()));
136
145
// Only the first level of reborrows need to be consider. All nested inner
137
146
// adjacent reborrows and phis are encapsulated within their lifetimes.
138
147
SILPhiArgument *arg;
139
148
if ((arg = dyn_cast<SILPhiArgument>(getCurrentDef ())) && arg->isPhi ()) {
140
149
visitInnerAdjacentPhis (arg, [&](SILArgument *reborrow) {
141
- defUseWorklist. insert (Def::reborrow (reborrow));
150
+ addDefToWorklist (Def::reborrow (reborrow));
142
151
return true ;
143
152
});
144
153
}
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 ();
147
158
LLVM_DEBUG (llvm::dbgs () << " Uses of value:\n " ;
148
159
value->print (llvm::dbgs ()));
149
160
@@ -154,11 +165,11 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
154
165
auto *user = use->getUser ();
155
166
// Recurse through copies.
156
167
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
157
- defUseWorklist. insert (Def::copy (copy));
168
+ addDefToWorklist (Def::copy (copy));
158
169
continue ;
159
170
}
160
171
if (auto *bfi = dyn_cast<BorrowedFromInst>(user)) {
161
- defUseWorklist. insert (Def::borrowedFrom (bfi));
172
+ addDefToWorklist (Def::borrowedFrom (bfi));
162
173
continue ;
163
174
}
164
175
// Handle debug_value instructions separately.
@@ -245,7 +256,7 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
245
256
// This branch reborrows a guaranteed phi whose lifetime is dependent on
246
257
// currentDef. Uses of the reborrowing phi extend liveness.
247
258
auto *reborrow = PhiOperand (use).getValue ();
248
- defUseWorklist. insert (Def::reborrow (reborrow));
259
+ addDefToWorklist (Def::reborrow (reborrow));
249
260
break ;
250
261
}
251
262
}
@@ -1152,6 +1163,15 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1152
1163
// Shadow defUseWorklist in order to constrain its uses.
1153
1164
auto &defUseWorklist = this ->defUseWorklist ;
1154
1165
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
+
1155
1175
InstructionSetVector instsToDelete (getCurrentDef ()->getFunction ());
1156
1176
1157
1177
// Visit each operand in the def-use chain.
@@ -1162,7 +1182,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1162
1182
auto *user = use->getUser ();
1163
1183
// Recurse through copies.
1164
1184
if (auto *copy = dyn_cast<CopyValueInst>(user)) {
1165
- defUseWorklist. insert (Def::copy (copy));
1185
+ addDefToWorklist (Def::copy (copy));
1166
1186
return true ;
1167
1187
}
1168
1188
if (destroys.contains (user)) {
@@ -1197,18 +1217,22 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1197
1217
return true ;
1198
1218
};
1199
1219
1200
- defUseWorklist.initialize (Def::root (getCurrentDef ()));
1220
+ defUseWorklist.clear ();
1221
+ addDefToWorklist (Def::root (getCurrentDef ()));
1201
1222
// 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) {
1204
1228
case Def::Kind::BorrowedFrom:
1205
1229
case Def::Kind::Reborrow:
1206
1230
// Direct uses of these defs never need to be rewritten. Being guaranteed
1207
1231
// values, none of their direct uses consume an owned value.
1208
1232
assert (def.getValue ()->getOwnershipKind () == OwnershipKind::Guaranteed);
1209
1233
break ;
1210
1234
case Def::Kind::Root: {
1211
- SILValue value = def-> getValue ();
1235
+ SILValue value = def. getValue ();
1212
1236
for (auto useIter = value->use_begin (), endIter = value->use_end ();
1213
1237
useIter != endIter;) {
1214
1238
Operand *use = *useIter++;
@@ -1219,7 +1243,7 @@ void CanonicalizeOSSALifetime::rewriteCopies(
1219
1243
break ;
1220
1244
}
1221
1245
case Def::Kind::Copy: {
1222
- SILValue value = def-> getValue ();
1246
+ SILValue value = def. getValue ();
1223
1247
CopyValueInst *srcCopy = cast<CopyValueInst>(value);
1224
1248
// Recurse through copies while replacing their uses.
1225
1249
Operand *reusedCopyOp = nullptr ;
0 commit comments