@@ -338,33 +338,50 @@ static bool memInstMustConsume(Operand *memOper) {
338338// / These are cases where we want to treat the end of the function as a liveness
339339// / use to ensure that we reinitialize \p value before the end of the function
340340// / 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+ }
359366 }
360367 }
361368
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+ }
368385 }
369386 }
370387
@@ -481,7 +498,7 @@ struct UseState {
481498 initializeLiveness (FieldSensitiveMultiDefPrunedLiveRange &prunedLiveness);
482499
483500 void initializeInOutTermUsers () {
484- if (!isInOutDefThatNeedsEndOfFunctionLiveness (address-> getOperand () ))
501+ if (!isInOutDefThatNeedsEndOfFunctionLiveness (address))
485502 return ;
486503
487504 SmallVector<SILBasicBlock *, 8 > exitBlocks;
0 commit comments