diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 9d265af58c019f..c575c50071756d 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6670,7 +6670,7 @@ class Compiler GenTree* fgMorphCopyBlock(GenTree* tree); private: GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr); - void fgTryReplaceStructLocalWithFields(GenTree** use); + bool fgTryReplaceStructLocalWithFields(GenTree** use); GenTree* fgMorphFinalizeIndir(GenTreeIndir* indir); GenTree* fgOptimizeCast(GenTreeCast* cast); GenTree* fgOptimizeCastOnStore(GenTree* store); diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 43390fd874418a..fc99dacca45b16 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -2287,6 +2287,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) #else *use = fieldList->SoleFieldOrThis(); #endif + *use = fgMorphTree(*use); } else { @@ -2335,7 +2336,8 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) // Try to see if we can use the promoted fields to pass this argument. // - if (varDsc->lvPromoted && (varDsc->lvFieldCnt == arg->AbiInfo.CountRegsAndStackSlots())) + if (varDsc->lvPromoted && !varDsc->lvDoNotEnregister && + (varDsc->lvFieldCnt == arg->AbiInfo.CountRegsAndStackSlots())) { bool fieldsMatch = true; @@ -2366,6 +2368,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) if (fieldsMatch) { newArg = fgMorphLclToFieldList(lclNode)->SoleFieldOrThis(); + newArg = fgMorphTree(newArg); } } } @@ -2511,7 +2514,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) lvaSetVarDoNotEnregister(lclVar->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField)); } } - result->SetMorphed(this); + result = fgMorphTree(result); return result; } else @@ -2532,7 +2535,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg) } GenTree* indir = gtNewIndir(type, addr); - indir->SetMorphed(this, /* doChildren*/ true); + indir->SetMorphed(this, /* doChildren */ true); return indir; } }; @@ -2593,16 +2596,15 @@ GenTreeFieldList* Compiler::fgMorphLclToFieldList(GenTreeLclVar* lcl) unsigned fieldLclNum = varDsc->lvFieldLclStart; GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList(); - fieldList->SetMorphed(this); for (unsigned i = 0; i < fieldCount; i++) { LclVarDsc* fieldVarDsc = lvaGetDesc(fieldLclNum); GenTree* lclVar = gtNewLclvNode(fieldLclNum, fieldVarDsc->TypeGet()); - lclVar->SetMorphed(this); fieldList->AddField(this, lclVar, fieldVarDsc->lvFldOffset, fieldVarDsc->TypeGet()); fieldLclNum++; } + return fieldList; } @@ -8366,7 +8368,10 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA GenTree*& retVal = tree->AsOp()->ReturnValueRef(); if ((retVal != nullptr) && ((genReturnBB == nullptr) || (compCurBB == genReturnBB))) { - fgTryReplaceStructLocalWithFields(&retVal); + if (fgTryReplaceStructLocalWithFields(&retVal)) + { + retVal = fgMorphTree(retVal); + } } break; } @@ -8424,19 +8429,22 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // Notes: // Currently only called when the tree parent is a GT_RETURN/GT_SWIFT_ERROR_RET. // -void Compiler::fgTryReplaceStructLocalWithFields(GenTree** use) +bool Compiler::fgTryReplaceStructLocalWithFields(GenTree** use) { if (!(*use)->OperIs(GT_LCL_VAR)) { - return; + return false; } LclVarDsc* varDsc = lvaGetDesc((*use)->AsLclVar()); - if (!varDsc->lvDoNotEnregister && varDsc->lvPromoted) + if (varDsc->lvDoNotEnregister || !varDsc->lvPromoted) { - *use = fgMorphLclToFieldList((*use)->AsLclVar()); + return false; } + + *use = fgMorphLclToFieldList((*use)->AsLclVar()); + return true; } //------------------------------------------------------------------------ diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.cs b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.cs new file mode 100644 index 00000000000000..7e501802f43021 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v2.5 on 2025-03-13 04:54:06 +// Run on X64 Linux +// Seed: 15128240988293741626-vectort,vector128,vector256,x86aes,x86avx,x86avx2,x86bmi1,x86bmi1x64,x86bmi2,x86bmi2x64,x86fma,x86lzcnt,x86lzcntx64,x86pclmulqdq,x86popcnt,x86popcntx64,x86sse,x86ssex64,x86sse2,x86sse2x64,x86sse3,x86sse41,x86sse41x64,x86sse42,x86sse42x64,x86ssse3,x86x86base +// Reduced from 188.7 KiB to 0.8 KiB in 00:01:09 +// Debug: Outputs 0 +// Release: Outputs 1 +using System; +using System.Numerics; +using System.Runtime.Intrinsics; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_113488 +{ + [Fact] + public static int TestEntryPoint() + { + S0 vr0 = default(S0); + return M4(vr0, Vector256.Create(vr0.M7())); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int M4(S0 arg0, Vector256 arg1) + { + return arg0.F0 == 0 ? 100 : 101; + } + + private struct S0 + { + public uint F0; + [MethodImpl(MethodImplOptions.NoInlining)] + public ushort M7() + { + this.F0 = 1; + return 0; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.csproj new file mode 100644 index 00000000000000..de6d5e08882e86 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_113488/Runtime_113488.csproj @@ -0,0 +1,8 @@ + + + True + + + + +