Description
Description
MethodImplOptions.NoOptimization
flag seems to be ignored when the method is inlined.
Reproduction Steps
using System;
using System.Threading;
using System.Runtime.CompilerServices;
public class C
{
private int _field;
public void N()
{
_field++;
}
[MethodImpl(MethodImplOptions.NoOptimization)]
public void Wrapper()
{
N();
}
public void Test(long count)
{
for (long i = 0; i < count; ++i)
{
Wrapper();
}
}
}
Expected behavior
The inlined method is not optimized. In this example, the wrapped call should not be inlined.
Actual behavior
The inlined method is optimized. The wrapped call is also inlined.
Regression?
Not sure.
Known Workarounds
Add MethodImplOptions.NoInlining
flag.
Configuration
Windows 10 (10.0.19045.5247/22H2/2022Update)
AMD Ryzen 7 9800X3D 4.70GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.101
[Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
DefaultJob : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Other information
Investigation of improving BenchmarkDotNet (dotnet/BenchmarkDotNet#2334). The attempt is to call the benchmarked method directly without inlining the call. NoInlining
flag on the wrapper method seems to work well for most CPUs (tested on AMD Phenom II, AMD Zen 3, Intel Core 9, Apple M3), but gets bad weird results specifically on AMD Zen 4+ architectures. Inlining the wrapper method seemed to get good timings with the test, but bad disassembly due to both calls getting inlined (and possibly incorrect results if such benchmark methods are actually inlined and optimized). Not sure what to do about it.