From 4711e7aee64372c2c28b36a013f5f67641e476d7 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 8 Apr 2026 15:56:49 +0200 Subject: [PATCH 1/4] JIT: Handle writes to promoted locals in `AliasSet::AddNode` --- src/coreclr/jit/sideeffects.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/coreclr/jit/sideeffects.cpp b/src/coreclr/jit/sideeffects.cpp index 5f90c8d90456c7..a3f63b07e362ba 100644 --- a/src/coreclr/jit/sideeffects.cpp +++ b/src/coreclr/jit/sideeffects.cpp @@ -318,6 +318,19 @@ void AliasSet::AddNode(Compiler* compiler, GenTree* node) if (nodeInfo.IsLclVarWrite()) { m_lclVarWrites.Add(compiler, nodeInfo.LclNum()); + + LclVarDsc* dsc = compiler->lvaGetDesc(nodeInfo.LclNum()); + if (dsc->lvIsStructField) + { + m_lclVarWrites.Add(compiler, dsc->lvParentLcl); + } + else if (dsc->lvPromoted) + { + for (unsigned i = 0; i < dsc->lvFieldCnt; i++) + { + m_lclVarWrites.Add(compiler, dsc->lvFieldLclStart + i); + } + } } } From 146264b7ad292f613257e10df13b9de47e544f26 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 15 Apr 2026 10:34:06 +0200 Subject: [PATCH 2/4] Add test --- .../JitBlue/Runtime_126414/Runtime_126414.cs | 62 +++++++++++++++++++ .../Runtime_126414/Runtime_126414.csproj | 9 +++ 2 files changed, 71 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.csproj diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs new file mode 100644 index 00000000000000..d7c5d9cc271c57 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using Xunit; + +namespace Runtime_126414; + +public readonly struct Endpoint +{ + public Endpoint(Endpoint e) + { + A = e.A; + B = e.B; + C = e.C; + } + + public Endpoint(int a, int b, int c) { A = a; B = b; C = c; } + + public int A { get; } + public int B { get; } + public int C { get; } +} + +public sealed class Range +{ + private readonly Endpoint m_start; + private readonly Endpoint m_end; + + // Using AggressiveOptimization to force reproduction of the bug which would eventually occur when tiered compilation optimizes the constructor + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + public Range(Endpoint start, Endpoint end) + { + m_start = new Endpoint(start); // Copy via copy constructor + m_end = new Endpoint(end); // Copy via copy constructor + } + + public int Length => m_end.A - m_start.A; +} + +public class Program +{ + [Fact] + public static int TestEntryPoint() + { + const int expected = 5759; + + for (int i = 0; i < 10000; i++) + { + var r = new Range(new Endpoint(100, 0, 0), new Endpoint(100 + expected, 0, 0)); + + if (r.Length != expected) + { + Console.WriteLine($"FAIL at iteration {i}: Length={r.Length} (expected {expected}), hex=0x{r.Length:X}"); + return 101; + } + } + + Console.WriteLine($"PASS: 10000 iterations, Length always = {expected}"); + return 100; + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.csproj new file mode 100644 index 00000000000000..501217e4d86892 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.csproj @@ -0,0 +1,9 @@ + + + None + True + + + + + From 0a43599995216e908d1f176022cef0643ce1c072 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 15 Apr 2026 11:12:48 +0200 Subject: [PATCH 3/4] Fix test --- .../JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs index d7c5d9cc271c57..a30ee3bb85b4da 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Runtime.CompilerServices; using Xunit; @@ -59,4 +60,4 @@ public static int TestEntryPoint() Console.WriteLine($"PASS: 10000 iterations, Length always = {expected}"); return 100; } -} \ No newline at end of file +} From 2feed844843a79615c40d9053f0e79113daafc75 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 15 Apr 2026 11:27:48 +0200 Subject: [PATCH 4/4] Another fix --- .../JitBlue/Runtime_126414/Runtime_126414.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs index a30ee3bb85b4da..f71b0d6e5f7ba4 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_126414/Runtime_126414.cs @@ -46,18 +46,15 @@ public static int TestEntryPoint() { const int expected = 5759; - for (int i = 0; i < 10000; i++) - { - var r = new Range(new Endpoint(100, 0, 0), new Endpoint(100 + expected, 0, 0)); + var r = new Range(new Endpoint(100, 0, 0), new Endpoint(100 + expected, 0, 0)); - if (r.Length != expected) - { - Console.WriteLine($"FAIL at iteration {i}: Length={r.Length} (expected {expected}), hex=0x{r.Length:X}"); - return 101; - } + if (r.Length != expected) + { + Console.WriteLine($"FAIL: Length={r.Length} (expected {expected}), hex=0x{r.Length:X}"); + return 101; } - Console.WriteLine($"PASS: 10000 iterations, Length always = {expected}"); + Console.WriteLine($"PASS: Length = {expected}"); return 100; } }