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) {
132132bool 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