diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index dd1dc0e70d371..3dddce9005dfb 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -16961,38 +16961,71 @@ const GenTreeLclVarCommon* GenTree::IsLocalAddrExpr() const } //------------------------------------------------------------------------ -// IsImplicitByrefParameterValue: determine if this tree is the entire -// value of a local implicit byref parameter +// IsImplicitByrefParameterValuePreMorph: +// Determine if this tree represents the value of an implicit byref +// parameter, and if so return the tree for the parameter. To be used +// before implicit byrefs have been morphed. // // Arguments: -// compiler -- compiler instance +// compiler - compiler instance // // Return Value: -// GenTreeLclVar node for the local, or nullptr. +// Node for the local, or nullptr. // -GenTreeLclVar* GenTree::IsImplicitByrefParameterValue(Compiler* compiler) +GenTreeLclVarCommon* GenTree::IsImplicitByrefParameterValuePreMorph(Compiler* compiler) { #if FEATURE_IMPLICIT_BYREFS && !defined(TARGET_LOONGARCH64) // TODO-LOONGARCH64-CQ: enable this. - GenTreeLclVar* lcl = nullptr; + GenTreeLclVarCommon* lcl = OperIsLocal() ? AsLclVarCommon() : nullptr; - if (OperIs(GT_LCL_VAR)) + if ((lcl != nullptr) && compiler->lvaIsImplicitByRefLocal(lcl->GetLclNum())) { - lcl = AsLclVar(); + return lcl; } - else if (OperIsIndir()) + +#endif // FEATURE_IMPLICIT_BYREFS && !defined(TARGET_LOONGARCH64) + + return nullptr; +} + +//------------------------------------------------------------------------ +// IsImplicitByrefParameterValuePostMorph: +// Determine if this tree represents the value of an implicit byref +// parameter, and if so return the tree for the parameter. To be used after +// implicit byrefs have been morphed. +// +// Arguments: +// compiler - compiler instance +// addr - [out] tree representing the address computation on top of the implicit byref. +// Will be the same as the return value if the whole implicit byref is used, for example. +// +// Return Value: +// Node for the local, or nullptr. +// +GenTreeLclVar* GenTree::IsImplicitByrefParameterValuePostMorph(Compiler* compiler, GenTree** addr) +{ +#if FEATURE_IMPLICIT_BYREFS && !defined(TARGET_LOONGARCH64) // TODO-LOONGARCH64-CQ: enable this. + + if (!OperIsIndir()) { - GenTree* addr = AsIndir()->Addr(); + return nullptr; + } - if (addr->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR)) - { - lcl = addr->AsLclVar(); - } + *addr = AsIndir()->Addr(); + GenTree* innerAddr = *addr; + + while (innerAddr->OperIs(GT_ADD) && innerAddr->gtGetOp2()->IsCnsIntOrI()) + { + innerAddr = innerAddr->gtGetOp1(); } - if ((lcl != nullptr) && compiler->lvaIsImplicitByRefLocal(lcl->GetLclNum())) + if (innerAddr->OperIs(GT_LCL_VAR)) { - return lcl; + GenTreeLclVar* lcl = innerAddr->AsLclVar(); + if (compiler->lvaIsImplicitByRefLocal(lcl->GetLclNum())) + { + return lcl; + } } #endif // FEATURE_IMPLICIT_BYREFS && !defined(TARGET_LOONGARCH64) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 790d14f284177..5d2ad550e3ec5 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1970,9 +1970,8 @@ struct GenTree return const_cast(static_cast(this)->IsLocalAddrExpr()); } - // Determine if this tree represents the value of an entire implicit byref parameter, - // and if so return the tree for the parameter. - GenTreeLclVar* IsImplicitByrefParameterValue(Compiler* compiler); + GenTreeLclVarCommon* IsImplicitByrefParameterValuePreMorph(Compiler* compiler); + GenTreeLclVar* IsImplicitByrefParameterValuePostMorph(Compiler* compiler, GenTree** addr); // Determine whether this is an assignment tree of the form X = X (op) Y, // where Y is an arbitrary tree, and X is a lclVar. diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index c16730d655a20..d251e9e1c2029 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -3947,7 +3947,9 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) // if (opts.OptimizationEnabled() && arg->AbiInfo.PassedByRef) { - GenTreeLclVarCommon* implicitByRefLcl = argx->IsImplicitByrefParameterValue(this); + GenTree* implicitByRefLclAddr; + GenTreeLclVarCommon* implicitByRefLcl = + argx->IsImplicitByrefParameterValuePostMorph(this, &implicitByRefLclAddr); GenTreeLclVarCommon* lcl = implicitByRefLcl; if ((lcl == nullptr) && argx->OperIsLocal()) @@ -3993,7 +3995,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) { if (implicitByRefLcl != nullptr) { - arg->SetEarlyNode(lcl); + arg->SetEarlyNode(implicitByRefLclAddr); } else { @@ -5890,8 +5892,8 @@ bool Compiler::fgCallHasMustCopyByrefParameter(GenTreeCall* callee) // and so still be able to avoid a struct copy. if (opts.OptimizationEnabled()) { - // First, see if this arg is an implicit byref param. - GenTreeLclVar* const lcl = arg.GetNode()->IsImplicitByrefParameterValue(this); + // First, see if this is an arg off of an implicit byref param. + GenTreeLclVarCommon* const lcl = arg.GetNode()->IsImplicitByrefParameterValuePreMorph(this); if (lcl != nullptr) { @@ -5963,7 +5965,7 @@ bool Compiler::fgCallHasMustCopyByrefParameter(GenTreeCall* callee) if (arg2.AbiInfo.IsStruct && arg2.AbiInfo.PassedByRef) { GenTreeLclVarCommon* const lcl2 = - arg2.GetNode()->IsImplicitByrefParameterValue(this); + arg2.GetNode()->IsImplicitByrefParameterValuePreMorph(this); if ((lcl2 != nullptr) && (lclNum == lcl2->GetLclNum())) {