Closed
Description
Description
If a call to Unsafe.As<A, B>()
and another call that uses the result (e.g., ToString()
) are inlined by JIT, it results in bad codegen. If inlined manually, codegen is correct.
Reproduction Steps
Bad codegen sample: https://godbolt.org/z/YEoYM7xY5
Minimal repro:
using System.Runtime.CompilerServices;
using System.Text;
internal static class Program
{
static void Main()
{
var sb = new Holder();
while (true)
{
var s = Bind(ref sb);
if (s.Length != 0)
{
Console.WriteLine("StringBuilder.ToString() returned: " + s);
return;
}
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static string Bind(ref Holder parameters) => GetString(parameters.GetBuilder());
public static string GetString(StringBuilder sb) => sb.ToString();
}
internal struct Holder
{
internal StringBuilder.AppendInterpolatedStringHandler _h;
public Holder() => _h = new(0, 0, new());
internal StringBuilder GetBuilder() => Unsafe.As<StringBuilder.AppendInterpolatedStringHandler, StringBuilder>(ref _h);
}
Expected behavior
StringBuilder:ToString()
is called (asm listing after manually inlining GetString):
; Assembly listing for method Program:Bind(byref):System.String (Tier1)
; Emitting BLENDED_CODE for X64 with AVX - Windows
; Tier1 code
; optimized code
; rsp based frame
; partially interruptible
; 0 inlinees with PGO data; 1 single block inlinees; 0 inlinees without PGO data
G_M000_IG01: ;; offset=0x0000
sub rsp, 40
G_M000_IG02: ;; offset=0x0004
mov rcx, gword ptr [rcx]
cmp dword ptr [rcx], ecx
call [System.Text.StringBuilder:ToString():System.String:this]
nop
G_M000_IG03: ;; offset=0x0010
add rsp, 40
ret
Actual behavior
Object:ToString()
is inlined instead:
; Assembly listing for method Program:Bind(byref):System.String (Tier1)
; Emitting BLENDED_CODE for X64 with AVX - Windows
; Tier1 code
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; 1 inlinees with PGO data; 3 single block inlinees; 0 inlinees without PGO data
G_M000_IG01: ;; offset=0x0000
sub rsp, 40
G_M000_IG02: ;; offset=0x0004
mov rcx, gword ptr [rcx]
cmp byte ptr [rcx], cl
call System.Object:GetType():System.Type:this
mov rcx, rax
mov edx, 1
call [System.RuntimeType:GetCachedName(int):System.String:this]
nop
G_M000_IG03: ;; offset=0x001D
add rsp, 40
ret
Regression?
This worked correctly in .NET 7
Known Workarounds
No response
Configuration
.NET 8.0.100-rc.2.23502.2, Windows x64
Other information
No response