Skip to content

Commit 03635a7

Browse files
authored
JIT: Kill assertions about struct local when skipping field stores in block morph (#115556)
If we skip storing a field local because we know it is dead, then assertions about the struct local are no longer valid, so invalidate them in that case. Without this change we could end up using the assertion about the struct local to remove a future store to the particular field, which would leave no zeroing of that field, and would be observable.
1 parent 4d4936b commit 03635a7

File tree

5 files changed

+48
-2
lines changed

5 files changed

+48
-2
lines changed

src/coreclr/jit/morphblock.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,6 @@ void MorphInitBlockHelper::PropagateBlockAssertions()
242242
//
243243
void MorphInitBlockHelper::PropagateExpansionAssertions()
244244
{
245-
// Consider doing this for FieldByField as well
246-
//
247245
if (m_comp->optLocalAssertionProp && (m_transformationDecision == BlockTransformation::OneStoreBlock))
248246
{
249247
m_comp->fgAssertionGen(m_store);
@@ -400,6 +398,7 @@ void MorphInitBlockHelper::TryInitFieldByField()
400398
if (m_comp->fgGlobalMorph && m_dstLclNode->IsLastUse(i))
401399
{
402400
JITDUMP("Field-by-field init skipping write to dead field V%02u\n", fieldLclNum);
401+
m_comp->fgKillDependentAssertionsSingle(m_dstLclNum DEBUGARG(m_store));
403402
continue;
404403
}
405404

@@ -1242,6 +1241,7 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
12421241
{
12431242
INDEBUG(unsigned dstFieldLclNum = m_comp->lvaGetDesc(m_dstLclNum)->lvFieldLclStart + i);
12441243
JITDUMP("Field-by-field copy skipping write to dead field V%02u\n", dstFieldLclNum);
1244+
m_comp->fgKillDependentAssertionsSingle(m_dstLclNum DEBUGARG(m_store));
12451245
continue;
12461246
}
12471247

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
using System;
5+
using System.Runtime.CompilerServices;
6+
using Xunit;
7+
8+
public static class Runtime_113658
9+
{
10+
[Fact]
11+
public static int TestEntryPoint()
12+
{
13+
FillStackWithGarbage();
14+
long? nullable = FaultyDefaultNullable<long?>();
15+
return (int)(100 + nullable.GetValueOrDefault());
16+
}
17+
18+
[MethodImpl(MethodImplOptions.NoInlining)]
19+
private static void FillStackWithGarbage()
20+
{
21+
stackalloc byte[256].Fill(0xcc);
22+
}
23+
24+
[MethodImpl(MethodImplOptions.NoInlining)]
25+
[SkipLocalsInit]
26+
private static T FaultyDefaultNullable<T>()
27+
{
28+
// When T is a Nullable<T> (and only in that case), we support returning null
29+
if (default(T) is null && typeof(T).IsValueType)
30+
return default!;
31+
32+
throw new InvalidOperationException("Not nullable");
33+
}
34+
}
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>

src/tests/JIT/Regression/JitBlue/Runtime_114358/Runtime_114358.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
3+
34
// Found by Antigen
45
// Reduced from 206.63 KB to 1.9 KB.
56

src/tests/JIT/Regression/JitBlue/Runtime_114978/Runtime_114978.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
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+
14
// Generated by Fuzzlyn v2.7 on 2025-04-23 21:44:41
25
// Run on X64 Windows
36
// Seed: 3309115426102150651-vectort,vector128,vector256,vector512,x86aes,x86avx,x86avx2,x86avx512bw,x86avx512bwvl,x86avx512cd,x86avx512cdvl,x86avx512dq,x86avx512dqvl,x86avx512f,x86avx512fvl,x86avx512fx64,x86avx512vbmi,x86avx512vbmivl,x86bmi1,x86bmi1x64,x86bmi2,x86bmi2x64,x86fma,x86lzcnt,x86lzcntx64,x86pclmulqdq,x86popcnt,x86popcntx64,x86sse,x86ssex64,x86sse2,x86sse2x64,x86sse3,x86sse41,x86sse41x64,x86sse42,x86sse42x64,x86ssse3,x86x86base

0 commit comments

Comments
 (0)