Skip to content

Commit 5c4a80e

Browse files
authored
JIT: Ensure fgTryMorphStructArg morphs created trees (#113496)
In particular we could create `LCL_FLD` or `LCL_VAR` nodes for address exposed locals without marking them with `GTF_GLOB_REF`. This would result in not creating some necessary copies.
1 parent 7b0fbc8 commit 5c4a80e

File tree

4 files changed

+68
-11
lines changed

4 files changed

+68
-11
lines changed

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6673,7 +6673,7 @@ class Compiler
66736673
GenTree* fgMorphCopyBlock(GenTree* tree);
66746674
private:
66756675
GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr);
6676-
void fgTryReplaceStructLocalWithFields(GenTree** use);
6676+
bool fgTryReplaceStructLocalWithFields(GenTree** use);
66776677
GenTree* fgMorphFinalizeIndir(GenTreeIndir* indir);
66786678
GenTree* fgOptimizeCast(GenTreeCast* cast);
66796679
GenTree* fgOptimizeCastOnStore(GenTree* store);

src/coreclr/jit/morph.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2287,6 +2287,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg)
22872287
#else
22882288
*use = fieldList->SoleFieldOrThis();
22892289
#endif
2290+
*use = fgMorphTree(*use);
22902291
}
22912292
else
22922293
{
@@ -2335,7 +2336,8 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg)
23352336

23362337
// Try to see if we can use the promoted fields to pass this argument.
23372338
//
2338-
if (varDsc->lvPromoted && (varDsc->lvFieldCnt == arg->AbiInfo.CountRegsAndStackSlots()))
2339+
if (varDsc->lvPromoted && !varDsc->lvDoNotEnregister &&
2340+
(varDsc->lvFieldCnt == arg->AbiInfo.CountRegsAndStackSlots()))
23392341
{
23402342
bool fieldsMatch = true;
23412343

@@ -2366,6 +2368,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg)
23662368
if (fieldsMatch)
23672369
{
23682370
newArg = fgMorphLclToFieldList(lclNode)->SoleFieldOrThis();
2371+
newArg = fgMorphTree(newArg);
23692372
}
23702373
}
23712374
}
@@ -2511,7 +2514,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg)
25112514
lvaSetVarDoNotEnregister(lclVar->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField));
25122515
}
25132516
}
2514-
result->SetMorphed(this);
2517+
result = fgMorphTree(result);
25152518
return result;
25162519
}
25172520
else
@@ -2532,7 +2535,7 @@ bool Compiler::fgTryMorphStructArg(CallArg* arg)
25322535
}
25332536

25342537
GenTree* indir = gtNewIndir(type, addr);
2535-
indir->SetMorphed(this, /* doChildren*/ true);
2538+
indir->SetMorphed(this, /* doChildren */ true);
25362539
return indir;
25372540
}
25382541
};
@@ -2593,16 +2596,15 @@ GenTreeFieldList* Compiler::fgMorphLclToFieldList(GenTreeLclVar* lcl)
25932596
unsigned fieldLclNum = varDsc->lvFieldLclStart;
25942597

25952598
GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList();
2596-
fieldList->SetMorphed(this);
25972599

25982600
for (unsigned i = 0; i < fieldCount; i++)
25992601
{
26002602
LclVarDsc* fieldVarDsc = lvaGetDesc(fieldLclNum);
26012603
GenTree* lclVar = gtNewLclvNode(fieldLclNum, fieldVarDsc->TypeGet());
2602-
lclVar->SetMorphed(this);
26032604
fieldList->AddField(this, lclVar, fieldVarDsc->lvFldOffset, fieldVarDsc->TypeGet());
26042605
fieldLclNum++;
26052606
}
2607+
26062608
return fieldList;
26072609
}
26082610

@@ -8366,7 +8368,10 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
83668368
GenTree*& retVal = tree->AsOp()->ReturnValueRef();
83678369
if ((retVal != nullptr) && ((genReturnBB == nullptr) || (compCurBB == genReturnBB)))
83688370
{
8369-
fgTryReplaceStructLocalWithFields(&retVal);
8371+
if (fgTryReplaceStructLocalWithFields(&retVal))
8372+
{
8373+
retVal = fgMorphTree(retVal);
8374+
}
83708375
}
83718376
break;
83728377
}
@@ -8424,19 +8429,22 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
84248429
// Notes:
84258430
// Currently only called when the tree parent is a GT_RETURN/GT_SWIFT_ERROR_RET.
84268431
//
8427-
void Compiler::fgTryReplaceStructLocalWithFields(GenTree** use)
8432+
bool Compiler::fgTryReplaceStructLocalWithFields(GenTree** use)
84288433
{
84298434
if (!(*use)->OperIs(GT_LCL_VAR))
84308435
{
8431-
return;
8436+
return false;
84328437
}
84338438

84348439
LclVarDsc* varDsc = lvaGetDesc((*use)->AsLclVar());
84358440

8436-
if (!varDsc->lvDoNotEnregister && varDsc->lvPromoted)
8441+
if (varDsc->lvDoNotEnregister || !varDsc->lvPromoted)
84378442
{
8438-
*use = fgMorphLclToFieldList((*use)->AsLclVar());
8443+
return false;
84398444
}
8445+
8446+
*use = fgMorphLclToFieldList((*use)->AsLclVar());
8447+
return true;
84408448
}
84418449

84428450
//------------------------------------------------------------------------
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
// Generated by Fuzzlyn v2.5 on 2025-03-13 04:54:06
5+
// Run on X64 Linux
6+
// 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
7+
// Reduced from 188.7 KiB to 0.8 KiB in 00:01:09
8+
// Debug: Outputs 0
9+
// Release: Outputs 1
10+
using System;
11+
using System.Numerics;
12+
using System.Runtime.Intrinsics;
13+
using System.Runtime.CompilerServices;
14+
using Xunit;
15+
16+
public class Runtime_113488
17+
{
18+
[Fact]
19+
public static int TestEntryPoint()
20+
{
21+
S0 vr0 = default(S0);
22+
return M4(vr0, Vector256.Create<ushort>(vr0.M7()));
23+
}
24+
25+
[MethodImpl(MethodImplOptions.NoInlining)]
26+
private static int M4(S0 arg0, Vector256<ushort> arg1)
27+
{
28+
return arg0.F0 == 0 ? 100 : 101;
29+
}
30+
31+
private struct S0
32+
{
33+
public uint F0;
34+
[MethodImpl(MethodImplOptions.NoInlining)]
35+
public ushort M7()
36+
{
37+
this.F0 = 1;
38+
return 0;
39+
}
40+
}
41+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>True</Optimize>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="$(MSBuildProjectName).cs" />
7+
</ItemGroup>
8+
</Project>

0 commit comments

Comments
 (0)