@@ -338,33 +338,50 @@ static bool memInstMustConsume(Operand *memOper) {
338
338
// / These are cases where we want to treat the end of the function as a liveness
339
339
// / use to ensure that we reinitialize \p value before the end of the function
340
340
// / if we consume \p value in the function body.
341
- static bool isInOutDefThatNeedsEndOfFunctionLiveness (SILValue value) {
342
- if (auto *fArg = dyn_cast<SILFunctionArgument>(value)) {
343
- switch (fArg ->getArgumentConvention ()) {
344
- case SILArgumentConvention::Indirect_In:
345
- case SILArgumentConvention::Indirect_Out:
346
- case SILArgumentConvention::Indirect_In_Guaranteed:
347
- case SILArgumentConvention::Direct_Guaranteed:
348
- case SILArgumentConvention::Direct_Owned:
349
- case SILArgumentConvention::Direct_Unowned:
350
- case SILArgumentConvention::Pack_Guaranteed:
351
- case SILArgumentConvention::Pack_Owned:
352
- case SILArgumentConvention::Pack_Out:
353
- return false ;
354
- case SILArgumentConvention::Indirect_Inout:
355
- case SILArgumentConvention::Indirect_InoutAliasable:
356
- case SILArgumentConvention::Pack_Inout:
357
- LLVM_DEBUG (llvm::dbgs () << " Found inout arg: " << *fArg );
358
- return true ;
341
+ static bool isInOutDefThatNeedsEndOfFunctionLiveness (MarkMustCheckInst *markedAddr) {
342
+ SILValue operand = markedAddr->getOperand ();
343
+
344
+ // Check for inout types of arguments that are marked with consumable and
345
+ // assignable.
346
+ if (markedAddr->getCheckKind () ==
347
+ MarkMustCheckInst::CheckKind::ConsumableAndAssignable) {
348
+ if (auto *fArg = dyn_cast<SILFunctionArgument>(operand)) {
349
+ switch (fArg ->getArgumentConvention ()) {
350
+ case SILArgumentConvention::Indirect_In:
351
+ case SILArgumentConvention::Indirect_Out:
352
+ case SILArgumentConvention::Indirect_In_Guaranteed:
353
+ case SILArgumentConvention::Direct_Guaranteed:
354
+ case SILArgumentConvention::Direct_Owned:
355
+ case SILArgumentConvention::Direct_Unowned:
356
+ case SILArgumentConvention::Pack_Guaranteed:
357
+ case SILArgumentConvention::Pack_Owned:
358
+ case SILArgumentConvention::Pack_Out:
359
+ return false ;
360
+ case SILArgumentConvention::Indirect_Inout:
361
+ case SILArgumentConvention::Indirect_InoutAliasable:
362
+ case SILArgumentConvention::Pack_Inout:
363
+ LLVM_DEBUG (llvm::dbgs () << " Found inout arg: " << *fArg );
364
+ return true ;
365
+ }
359
366
}
360
367
}
361
368
362
- if (auto *pbi = dyn_cast<ProjectBoxInst>(value)) {
363
- if (auto *fArg = dyn_cast<SILFunctionArgument>(pbi->getOperand ())) {
364
- if (!fArg ->isClosureCapture ())
365
- return false ;
366
- LLVM_DEBUG (llvm::dbgs () << " Found inout arg: " << *fArg );
367
- return true ;
369
+ // See if we have an assignable_but_not_consumable from a project_box +
370
+ // function_argument. In this case, the value must be live at the end of the
371
+ // use, similar to an inout parameter.
372
+ //
373
+ // TODO: Rather than using a terminator, we might be able to use the
374
+ // end_access of the access marker instead. That would slightly change the
375
+ // model and this is semantically ok today.
376
+ if (markedAddr->getCheckKind () ==
377
+ MarkMustCheckInst::CheckKind::AssignableButNotConsumable) {
378
+ if (auto *pbi = dyn_cast<ProjectBoxInst>(stripAccessMarkers (operand))) {
379
+ if (auto *fArg = dyn_cast<SILFunctionArgument>(pbi->getOperand ())) {
380
+ if (!fArg ->isClosureCapture ())
381
+ return false ;
382
+ LLVM_DEBUG (llvm::dbgs () << " Found inout arg: " << *fArg );
383
+ return true ;
384
+ }
368
385
}
369
386
}
370
387
@@ -481,7 +498,7 @@ struct UseState {
481
498
initializeLiveness (FieldSensitiveMultiDefPrunedLiveRange &prunedLiveness);
482
499
483
500
void initializeInOutTermUsers () {
484
- if (!isInOutDefThatNeedsEndOfFunctionLiveness (address-> getOperand () ))
501
+ if (!isInOutDefThatNeedsEndOfFunctionLiveness (address))
485
502
return ;
486
503
487
504
SmallVector<SILBasicBlock *, 8 > exitBlocks;
0 commit comments