@@ -51,12 +51,6 @@ namespace {
5151
5252struct SILMoveOnlyWrappedTypeEliminatorVisitor
5353 : SILInstructionVisitor<SILMoveOnlyWrappedTypeEliminatorVisitor, bool > {
54- const llvm::SmallSetVector<SILArgument *, 8 > &touchedArgs;
55-
56- SILMoveOnlyWrappedTypeEliminatorVisitor (
57- const llvm::SmallSetVector<SILArgument *, 8 > &touchedArgs)
58- : touchedArgs(touchedArgs) {}
59-
6054 bool visitSILInstruction (SILInstruction *inst) {
6155 llvm::errs () << " Unhandled SIL Instruction: " << *inst;
6256 llvm_unreachable (" error" );
@@ -294,56 +288,76 @@ static bool isMoveOnlyWrappedTrivial(SILValue value) {
294288}
295289
296290bool SILMoveOnlyWrappedTypeEliminator::process () {
297- bool madeChange = true ;
291+ bool madeChange = false ;
298292
299- llvm::SmallSetVector<SILArgument *, 8 > touchedArgs;
300293 llvm::SmallSetVector<SILInstruction *, 8 > touchedInsts;
301294
295+ // For each value whose type is move-only wrapped:
296+ // - rewrite the value's type
297+ // - record its users for later visitation
298+ auto visitValue = [&touchedInsts, fn = fn,
299+ trivialOnly = trivialOnly](SILValue value) -> bool {
300+ if (!value->getType ().hasAnyMoveOnlyWrapping (fn))
301+ return false ;
302+
303+ // If we are looking at trivial only, skip non-trivial function args.
304+ if (trivialOnly && !isMoveOnlyWrappedTrivial (value))
305+ return false ;
306+
307+ for (auto *use : value->getNonTypeDependentUses ())
308+ touchedInsts.insert (use->getUser ());
309+
310+ if (isa<SILUndef>(value))
311+ value->replaceAllUsesWith (
312+ SILUndef::get (fn, value->getType ().removingAnyMoveOnlyWrapping (fn)));
313+ else
314+ value->unsafelyEliminateMoveOnlyWrapper (fn);
315+
316+ return true ;
317+ };
318+
302319 for (auto &bb : *fn) {
303320 for (auto *arg : bb.getArguments ()) {
304- if (! arg-> getType (). isMoveOnlyWrapped () &&
305- !arg-> getType (). isBoxedMoveOnlyWrappedType (fn) )
321+ bool relevant = visitValue ( arg);
322+ if (!relevant )
306323 continue ;
307324
308- // If we are looking at trivial only, skip non-trivial function args.
309- if (trivialOnly &&
310- !arg->getType ().removingMoveOnlyWrapper ().isTrivial (*fn))
311- continue ;
312-
313- arg->unsafelyEliminateMoveOnlyWrapper (fn);
314-
315325 // If our new type is trivial, convert the arguments ownership to
316326 // None. Otherwise, preserve the ownership kind of the argument.
317327 if (arg->getType ().isTrivial (*fn))
318328 arg->setOwnershipKind (OwnershipKind::None);
319- touchedArgs.insert (arg);
320- for (auto *use : arg->getNonTypeDependentUses ())
321- touchedInsts.insert (use->getUser ());
329+
330+ madeChange = true ;
322331 }
323332
324333 for (auto &ii : bb) {
325- for (SILValue v : ii.getResults ()) {
326- if (!v->getType ().isMoveOnlyWrapped () &&
327- !v->getType ().isBoxedMoveOnlyWrappedType (fn))
328- continue ;
329-
330- if (trivialOnly &&
331- !isMoveOnlyWrappedTrivial (v))
334+ bool touched = false ;
335+ for (SILValue value : ii.getResults ()) {
336+ bool relevant = visitValue (value);
337+ if (!relevant)
332338 continue ;
333339
334- v->unsafelyEliminateMoveOnlyWrapper (fn);
335- touchedInsts.insert (&ii);
336-
337- // Add all users as well. This ensures we visit things like
338- // destroy_value and end_borrow.
339- for (auto *use : v->getNonTypeDependentUses ())
340- touchedInsts.insert (use->getUser ());
341- madeChange = true ;
340+ touched = true ;
342341 }
342+ if (!touched)
343+ continue ;
344+ touchedInsts.insert (&ii);
345+
346+ madeChange = true ;
343347 }
344348 }
349+ // SILFunction::undefValues may grow during the loop.
350+ SmallVector<std::pair<SILType, SILUndef *>, 4 > originalUndefs (
351+ fn->getUndefValues ());
352+ for (auto pair : originalUndefs) {
353+ bool relevant = visitValue (pair.second );
354+ if (!relevant)
355+ continue ;
356+
357+ madeChange = true ;
358+ }
345359
346- SILMoveOnlyWrappedTypeEliminatorVisitor visitor (touchedArgs) ;
360+ SILMoveOnlyWrappedTypeEliminatorVisitor visitor;
347361 while (!touchedInsts.empty ()) {
348362 visitor.visit (touchedInsts.pop_back_val ());
349363 }
0 commit comments