diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 7a6246a988f..3d9e40e9fc2 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -387,6 +387,19 @@ private: #endif // DEBUG } + // If the inline was rejected and returns a retbuffer, then mark that + // local as DNER now so that promotion knows to leave it up to physical + // promotion. + if ((*use)->IsCall()) + { + CallArg* retBuffer = (*use)->AsCall()->gtArgs.GetRetBufferArg(); + if ((retBuffer != nullptr) && retBuffer->GetNode()->OperIs(GT_LCL_ADDR)) + { + m_compiler->lvaSetVarDoNotEnregister(retBuffer->GetNode()->AsLclVarCommon()->GetLclNum() + DEBUGARG(DoNotEnregisterReason::HiddenBufferStructArg)); + } + } + #if FEATURE_MULTIREG_RET // If an inline was rejected and the call returns a struct, we may // have deferred some work when importing call for cases where the diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 448ee995579..a84f3db3ff4 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -851,6 +851,12 @@ GenTree* Compiler::impStoreStruct(GenTree* store, GenTree* destAddr = impGetNodeAddr(store, CHECK_SPILL_ALL, &indirFlags); NewCallArg newArg = NewCallArg::Primitive(destAddr).WellKnown(wellKnownArgType); + if (destAddr->OperIs(GT_LCL_ADDR)) + { + lvaSetVarDoNotEnregister(destAddr->AsLclVarCommon()->GetLclNum() + DEBUGARG(DoNotEnregisterReason::HiddenBufferStructArg)); + } + #if !defined(TARGET_ARM) // Unmanaged instance methods on Windows or Unix X86 need the retbuf arg after the first (this) parameter if ((TargetOS::IsWindows || compUnixX86Abi()) && srcCall->IsUnmanaged()) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 87f67e1e330..74c8fd1add0 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -2570,9 +2570,11 @@ bool Compiler::StructPromotionHelper::CanPromoteStructVar(unsigned lclNum) return false; } - if (varDsc->IsAddressExposed()) + if (varDsc->lvDoNotEnregister) { - JITDUMP(" struct promotion of V%02u is disabled because it has already been marked address exposed\n", lclNum); + // Promoting structs that are marked DNER will result in dependent + // promotion. Allow physical promotion to handle these. + JITDUMP(" struct promotion of V%02u is disabled because it has already been marked DNER\n", lclNum); return false; } @@ -3173,7 +3175,6 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregister break; case DoNotEnregisterReason::HiddenBufferStructArg: JITDUMP("it is hidden buffer struct arg\n"); - assert(varDsc->IsHiddenBufferStructArg()); break; case DoNotEnregisterReason::DontEnregStructs: JITDUMP("struct enregistration is disabled\n");