@@ -60,6 +60,28 @@ namespace {
6060
6161struct SILMoveOnlyWrappedTypeEliminatorVisitor
6262 : SILInstructionVisitor<SILMoveOnlyWrappedTypeEliminatorVisitor, bool > {
63+
64+ // Instructions waiting to be visited.
65+ llvm::SmallSetVector<SILInstruction *, 8 > &pendingInsts;
66+ llvm::SmallVector<SILInstruction *, 8 > deferredInsts;
67+
68+ SILMoveOnlyWrappedTypeEliminatorVisitor (llvm::SmallSetVector<SILInstruction *, 8 > &pendingInsts):
69+ pendingInsts (pendingInsts)
70+ {}
71+
72+ // If 'user's operand is not yet visited, push it onto the end of
73+ // 'pendingInsts' and pretend we didn't see it yet. This is only relevant for
74+ // non-address operands in which ownership should be consistent.
75+ bool waitFor (SILInstruction *user, SILValue operand) {
76+ if (auto *def = operand.getDefiningInstruction ()) {
77+ if (pendingInsts.contains (def)) {
78+ deferredInsts.push_back (user);
79+ return false ;
80+ }
81+ }
82+ return true ;
83+ }
84+
6385 bool visitSILInstruction (SILInstruction *inst) {
6486 llvm::errs () << " Unhandled SIL Instruction: " << *inst;
6587 llvm_unreachable (" error" );
@@ -79,13 +101,19 @@ struct SILMoveOnlyWrappedTypeEliminatorVisitor
79101 }
80102
81103 bool visitStoreInst (StoreInst *si) {
104+ if (!waitFor (si, si->getSrc ())) {
105+ return false ;
106+ }
82107 if (!si->getSrc ()->getType ().isTrivial (*si->getFunction ()))
83108 return false ;
84109 si->setOwnershipQualifier (StoreOwnershipQualifier::Trivial);
85110 return true ;
86111 }
87112
88113 bool visitStoreBorrowInst (StoreBorrowInst *si) {
114+ if (!waitFor (si, si->getSrc ())) {
115+ return false ;
116+ }
89117 if (!si->getSrc ()->getType ().isTrivial (*si->getFunction ()))
90118 return false ;
91119 SILBuilderWithScope b (si);
@@ -332,6 +360,9 @@ bool SILMoveOnlyWrappedTypeEliminator::process() {
332360 return true ;
333361 };
334362
363+ // (1) Check each value's type for the MoveOnly wrapper, (2) strip the wrapper
364+ // type, and (3) add all uses to 'touchedInsts' in forward order for
365+ // efficiency.
335366 for (auto &bb : *fn) {
336367 for (auto *arg : bb.getArguments ()) {
337368 bool relevant = visitValue (arg);
@@ -377,9 +408,18 @@ bool SILMoveOnlyWrappedTypeEliminator::process() {
377408 madeChange = true ;
378409 }
379410
380- SILMoveOnlyWrappedTypeEliminatorVisitor visitor;
381- while (!touchedInsts.empty ()) {
382- visitor.visit (touchedInsts.pop_back_val ());
411+ SILMoveOnlyWrappedTypeEliminatorVisitor visitor{touchedInsts};
412+ while (true ) {
413+ while (!touchedInsts.empty ()) {
414+ visitor.visit (touchedInsts.pop_back_val ());
415+ }
416+ if (visitor.deferredInsts .empty ())
417+ break ;
418+
419+ for (auto *inst : visitor.deferredInsts ) {
420+ touchedInsts.insert (inst);
421+ }
422+ visitor.deferredInsts .clear ();
383423 }
384424
385425 return madeChange;
0 commit comments