@@ -51,12 +51,6 @@ namespace {
51
51
52
52
struct SILMoveOnlyWrappedTypeEliminatorVisitor
53
53
: SILInstructionVisitor<SILMoveOnlyWrappedTypeEliminatorVisitor, bool > {
54
- const llvm::SmallSetVector<SILArgument *, 8 > &touchedArgs;
55
-
56
- SILMoveOnlyWrappedTypeEliminatorVisitor (
57
- const llvm::SmallSetVector<SILArgument *, 8 > &touchedArgs)
58
- : touchedArgs(touchedArgs) {}
59
-
60
54
bool visitSILInstruction (SILInstruction *inst) {
61
55
llvm::errs () << " Unhandled SIL Instruction: " << *inst;
62
56
llvm_unreachable (" error" );
@@ -294,56 +288,76 @@ static bool isMoveOnlyWrappedTrivial(SILValue value) {
294
288
}
295
289
296
290
bool SILMoveOnlyWrappedTypeEliminator::process () {
297
- bool madeChange = true ;
291
+ bool madeChange = false ;
298
292
299
- llvm::SmallSetVector<SILArgument *, 8 > touchedArgs;
300
293
llvm::SmallSetVector<SILInstruction *, 8 > touchedInsts;
301
294
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
+
302
319
for (auto &bb : *fn) {
303
320
for (auto *arg : bb.getArguments ()) {
304
- if (! arg-> getType (). isMoveOnlyWrapped () &&
305
- !arg-> getType (). isBoxedMoveOnlyWrappedType (fn) )
321
+ bool relevant = visitValue ( arg);
322
+ if (!relevant )
306
323
continue ;
307
324
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
-
315
325
// If our new type is trivial, convert the arguments ownership to
316
326
// None. Otherwise, preserve the ownership kind of the argument.
317
327
if (arg->getType ().isTrivial (*fn))
318
328
arg->setOwnershipKind (OwnershipKind::None);
319
- touchedArgs.insert (arg);
320
- for (auto *use : arg->getNonTypeDependentUses ())
321
- touchedInsts.insert (use->getUser ());
329
+
330
+ madeChange = true ;
322
331
}
323
332
324
333
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)
332
338
continue ;
333
339
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 ;
342
341
}
342
+ if (!touched)
343
+ continue ;
344
+ touchedInsts.insert (&ii);
345
+
346
+ madeChange = true ;
343
347
}
344
348
}
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
+ }
345
359
346
- SILMoveOnlyWrappedTypeEliminatorVisitor visitor (touchedArgs) ;
360
+ SILMoveOnlyWrappedTypeEliminatorVisitor visitor;
347
361
while (!touchedInsts.empty ()) {
348
362
visitor.visit (touchedInsts.pop_back_val ());
349
363
}
0 commit comments