if (isArgToCall)
{
- JITDUMP("LocalAddressVisitor incrementing weighted ref count from %d to %d"
+ JITDUMP("LocalAddressVisitor incrementing weighted ref count from " FMT_WT " to " FMT_WT
" for implicit by-ref V%02d arg passed to call\n",
varDsc->lvRefCntWtd(RCS_EARLY), varDsc->lvRefCntWtd(RCS_EARLY) + 1, lclNum);
varDsc->incLvRefCntWtd(1, RCS_EARLY);
// We only check this for calls with small numbers of arguments,
// as the analysis cost will be quadratic.
//
- if (varDsc->lvRefCnt(RCS_EARLY) == 1)
+ const unsigned totalAppearances = varDsc->lvRefCnt(RCS_EARLY);
+ const unsigned callAppearances = (unsigned)varDsc->lvRefCntWtd(RCS_EARLY);
+ assert(totalAppearances >= callAppearances);
+
+ if (totalAppearances == 1)
{
JITDUMP("... yes, arg is the only appearance of V%02u\n", lclNum);
hasMustCopyByrefParameter = false;
}
+ else if (totalAppearances > callAppearances)
+ {
+ // lvRefCntWtd tracks the number of appearances of the arg at call sites.
+ // If this number doesn't match the regular ref count, there is
+ // a non-call appearance, and we must be conservative.
+ //
+ JITDUMP("... no, arg has %u non-call appearance(s)\n",
+ totalAppearances - callAppearances);
+ }
else if (argInfo->ArgCount() <= argLimit)
{
+ JITDUMP("... all %u appearance(s) are as implicit byref args to calls.\n"
+ "... Running alias analysis on this call's args\n",
+ totalAppearances);
GenTree* interferingArg = nullptr;
for (unsigned index2 = 0; index2 < argInfo->ArgCount(); ++index2)
{
--- /dev/null
+// 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 System.Runtime.InteropServices;
+
+class Runtime_56743_0
+{
+ [MethodImpl(MethodImplOptions.NoOptimization)]
+ static int Main()
+ {
+ int result = Foo(default, default);
+ return result == 0 ? 100 : -1;
+ }
+
+ static int Foo(S s, Span<S> span)
+ {
+ span = MemoryMarshal.CreateSpan(ref s, 1);
+ return Bar(s, span);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int Bar(S h, Span<S> s)
+ {
+ s[0].A = 10;
+ return h.A;
+ }
+
+ struct S
+ {
+ public int A, B, C, D;
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ </PropertyGroup>
+ <PropertyGroup>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// 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;
+
+unsafe class Runtime_56743_1
+{
+ [MethodImpl(MethodImplOptions.NoOptimization)]
+ static int Main()
+ {
+ int result = Foo(default);
+ return result == 0 ? 100 : -1;
+ }
+
+ static S* s_s;
+ static int Foo(S s)
+ {
+ s_s = &s;
+ return Bar(s);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int Bar(S h)
+ {
+ s_s->A = 10;
+ return h.A;
+ }
+
+ struct S
+ {
+ public int A, B, C, D;
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ </PropertyGroup>
+ <PropertyGroup>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// 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;
+
+unsafe class Runtime_56743_2
+{
+ [MethodImpl(MethodImplOptions.NoOptimization)]
+ static int Main()
+ {
+ int result = Foo(default);
+ return result == 0 ? 100 : -1;
+ }
+
+ static int Foo(S h)
+ {
+ h.H = &h;
+ return Bar(h);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int Bar(S h)
+ {
+ h.H->A = 10;
+ return h.A;
+ }
+
+ unsafe struct S
+ {
+ public int A, B;
+ public S* H;
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ </PropertyGroup>
+ <PropertyGroup>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+</Project>