@@ -5441,6 +5441,8 @@ bool CodeGen::genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarri
54415441#endif // !defined(TARGET_X86) || !NOGC_WRITE_BARRIERS
54425442}
54435443
5444+ int s_numUnnecessaryLastUseStructCopies;
5445+
54445446// Produce code for a GT_CALL node
54455447void CodeGen::genCall (GenTreeCall* call)
54465448{
@@ -5518,6 +5520,73 @@ void CodeGen::genCall(GenTreeCall* call)
55185520 }
55195521 }
55205522
5523+ for (CallArg& arg : call->gtArgs .Args ())
5524+ {
5525+ assert ((arg.GetEarlyNode () == nullptr ) != (arg.GetLateNode () == nullptr ));
5526+ if (!arg.AbiInfo .PassedByRef )
5527+ continue ;
5528+
5529+ GenTree* putArg = arg.GetNode ();
5530+ GenTree* arg = putArg->gtGetOp1 ();
5531+ if (!arg->OperIs (GT_LCL_VAR_ADDR))
5532+ continue ;
5533+
5534+ unsigned lclNum = arg->AsLclVarCommon ()->GetLclNum ();
5535+ if ((arg->gtFlags & GTF_VAR_DEATH) != 0 )
5536+ continue ;
5537+
5538+ GenTree* curNode = arg;
5539+ do
5540+ {
5541+ curNode = curNode->gtPrev ;
5542+
5543+ GenTree* storeData = nullptr ;
5544+ if (curNode->OperIsStoreBlk () && curNode->AsIndir ()->Addr ()->OperIsLocalAddr ())
5545+ {
5546+ GenTreeLclVarCommon* addr = curNode->AsIndir ()->Addr ()->AsLclVarCommon ();
5547+ if (addr->AsLclVarCommon ()->GetLclNum () == lclNum && addr->AsLclVarCommon ()->GetLclOffs () == 0 )
5548+ storeData = curNode->AsIndir ()->Data ();
5549+ }
5550+ else if (curNode->OperIsLocalStore ())
5551+ {
5552+ GenTreeLclVarCommon* addr = curNode->AsLclVarCommon ();
5553+ if (addr->GetLclNum () == lclNum && addr->GetLclOffs () == 0 )
5554+ storeData = curNode->AsLclVarCommon ()->Data ();
5555+ }
5556+ else
5557+ {
5558+ assert (!curNode->OperIsLocal () || curNode->AsLclVarCommon ()->GetLclNum () != lclNum);
5559+ }
5560+
5561+ if (storeData != nullptr )
5562+ {
5563+ GenTreeLclVarCommon* srcLcl = nullptr ;
5564+ if (storeData->OperIsIndir () && storeData->AsIndir ()->Addr ()->OperIsLocal ())
5565+ {
5566+ GenTreeLclVarCommon* lcl = storeData->AsIndir ()->Addr ()->AsLclVarCommon ();
5567+ if (compiler->lvaGetDesc (lcl)->lvIsImplicitByRef && !compiler->lvaGetDesc (lcl)->lvImplicitByRefAddrExposed )
5568+ srcLcl = lcl;
5569+ }
5570+ else if (storeData->OperIsLocal ())
5571+ {
5572+ GenTreeLclVarCommon* lcl = storeData->AsLclVarCommon ();
5573+ if (!compiler->lvaGetDesc (lcl)->IsAddressExposed ())
5574+ srcLcl = lcl;
5575+ }
5576+
5577+ if (srcLcl != nullptr )
5578+ {
5579+ if ((compiler->lvaGetPromotionType (srcLcl->GetLclNum ()) != Compiler::PROMOTION_TYPE_INDEPENDENT) && (srcLcl->gtFlags & GTF_VAR_DEATH) != 0 )
5580+ {
5581+ s_numUnnecessaryLastUseStructCopies++;
5582+ }
5583+ }
5584+
5585+ break ;
5586+ }
5587+ } while (curNode != LIR::AsRange (compiler->compCurBB ).FirstNode ());
5588+ }
5589+
55215590#if defined(TARGET_X86) || defined(UNIX_AMD64_ABI)
55225591 // The call will pop its arguments.
55235592 // for each putarg_stk:
0 commit comments