From 594a36433861a23c070f32aefcd3e8a30019cabc Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Wed, 23 Apr 2025 10:55:37 -0700 Subject: [PATCH] JIT: fix retyping error in object stack allocation Retype GT_STOREIND based on the store address, not the store data, since we need to know if we are retyping fields, and only know that when propagating from the local that forms the store address. Fixes #111922. --- src/coreclr/jit/objectalloc.cpp | 11 ++--- .../JIT/opt/ObjectStackAllocation/Retyping.cs | 47 +++++++++++++++++++ .../opt/ObjectStackAllocation/Retyping.csproj | 9 ++++ 3 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 src/tests/JIT/opt/ObjectStackAllocation/Retyping.cs create mode 100644 src/tests/JIT/opt/ObjectStackAllocation/Retyping.csproj diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp index c45af95d17e86a..28b76e0a8f5960 100644 --- a/src/coreclr/jit/objectalloc.cpp +++ b/src/coreclr/jit/objectalloc.cpp @@ -2039,16 +2039,11 @@ void ObjectAllocator::UpdateAncestorTypes(GenTree* tree, // It's either null or points to inside a stack-allocated object. parent->gtFlags |= GTF_IND_TGT_NOT_HEAP; } - } - else - { - assert(tree == parent->AsIndir()->Data()); - GenTree* const addr = parent->AsIndir()->Addr(); - // If we are storing to a GC struct field, we may need to retype the store + // If we are storing to a GC struct field we may need to retype the store // - if (retypeFields && parent->OperIs(GT_STOREIND) && (addr->OperIs(GT_FIELD_ADDR)) && - (varTypeIsGC(parent->TypeGet()))) + if (retypeFields && parent->OperIs(GT_STOREIND) && tree->OperIs(GT_FIELD_ADDR) && + varTypeIsGC(parent->TypeGet())) { parent->ChangeType(newType); } diff --git a/src/tests/JIT/opt/ObjectStackAllocation/Retyping.cs b/src/tests/JIT/opt/ObjectStackAllocation/Retyping.cs new file mode 100644 index 00000000000000..bdeb810eb79f13 --- /dev/null +++ b/src/tests/JIT/opt/ObjectStackAllocation/Retyping.cs @@ -0,0 +1,47 @@ +// 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.Reflection; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using Xunit; + +class C1 +{ + public C1(int x) { a = x; b = x; } + public int a; + public int b; +} + +struct S1 +{ + public S1(C1 z) { c = z; } + public int a; + public int b; + public C1 c; +} + +public class Runtime_111922 +{ + [Fact] + public static int Problem() + { + S1 s = new S1(new C1(4)); + return 95 + SubProblem(1, s); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int SubProblem(int x, S1 s) + { + s = new S1(new C1(5)); + + SideEffect(); + + C1 v = s.c; + return v.a; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void SideEffect() { } +} diff --git a/src/tests/JIT/opt/ObjectStackAllocation/Retyping.csproj b/src/tests/JIT/opt/ObjectStackAllocation/Retyping.csproj new file mode 100644 index 00000000000000..501217e4d86892 --- /dev/null +++ b/src/tests/JIT/opt/ObjectStackAllocation/Retyping.csproj @@ -0,0 +1,9 @@ + + + None + True + + + + +