@@ -6273,7 +6273,7 @@ bool GenTree::OperRequiresAsgFlag()
62736273 {
62746274 // If the call has return buffer argument, it produced a definition and hence
62756275 // should be marked with assignment.
6276- return AsCall()->GetLclRetBufArgNode() != nullptr ;
6276+ return AsCall()->IsOptimizingRetBufAsLocal() ;
62776277 }
62786278 return false;
62796279}
@@ -16138,7 +16138,7 @@ bool GenTree::DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bo
1613816138 }
1613916139 else if (OperIs(GT_CALL))
1614016140 {
16141- GenTree* retBufArg = AsCall()->GetLclRetBufArgNode( );
16141+ GenTree* retBufArg = comp->gtCallGetDefinedRetBufLclAddr(AsCall() );
1614216142 if (retBufArg == nullptr)
1614316143 {
1614416144 return false;
@@ -16180,7 +16180,7 @@ bool GenTree::DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bo
1618016180// Returns true if this GenTree defines a result which is based on the address of a local.
1618116181bool GenTree::DefinesLocalAddr(Compiler* comp, unsigned width, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire)
1618216182{
16183- if (OperGet() == GT_ADDR || OperGet() == GT_LCL_VAR_ADDR )
16183+ if (OperIs( GT_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR) )
1618416184 {
1618516185 GenTree* addrArg = this;
1618616186 if (OperGet() == GT_ADDR)
@@ -17864,6 +17864,57 @@ bool Compiler::gtIsStaticGCBaseHelperCall(GenTree* tree)
1786417864 return false;
1786517865}
1786617866
17867+ //------------------------------------------------------------------------
17868+ // gtCallGetDefinedRetBufLclAddr:
17869+ // Get the tree corresponding to the address of the retbuf taht this call defines.
17870+ //
17871+ // Parameters:
17872+ // call - The call node
17873+ //
17874+ // Returns:
17875+ // A tree representing the address of a local.
17876+ //
17877+ // Remarks:
17878+ // This function should not be used until after morph when local address
17879+ // nodes have been normalized. However, before that IsOptimizingRetBufAsLocal
17880+ // can be used to at least check if the call has a retbuf that we are
17881+ // optimizing.
17882+ //
17883+ GenTree* Compiler::gtCallGetDefinedRetBufLclAddr(GenTreeCall* call)
17884+ {
17885+ if (!call->IsOptimizingRetBufAsLocal())
17886+ {
17887+ return nullptr;
17888+ }
17889+
17890+ CallArg* retBufArg = call->gtArgs.GetRetBufferArg();
17891+ assert(retBufArg != nullptr);
17892+
17893+ GenTree* node = retBufArg->GetNode();
17894+ switch (node->OperGet())
17895+ {
17896+ // Get the value from putarg wrapper nodes
17897+ case GT_PUTARG_REG:
17898+ case GT_PUTARG_STK:
17899+ node = node->AsOp()->gtGetOp1();
17900+ break;
17901+
17902+ default:
17903+ break;
17904+ }
17905+
17906+ // This may be called very late to check validity of LIR.
17907+ node = node->gtSkipReloadOrCopy();
17908+
17909+ #ifdef DEBUG
17910+ unsigned size = typGetObjLayout(call->gtRetClsHnd)->GetSize();
17911+ GenTreeLclVarCommon* lcl;
17912+ assert(node->DefinesLocalAddr(this, size, &lcl, nullptr) && lvaGetDesc(lcl)->lvHiddenBufferStructArg);
17913+ #endif
17914+
17915+ return node;
17916+ }
17917+
1786717918//------------------------------------------------------------------------
1786817919// ParseArrayAddress: Rehydrate the array and index expression from ARR_ADDR.
1786917920//
0 commit comments