title: Why would the .NET JIT compiler decide to not inline or optimize away calls to empty static methods that have no side effects?
body: <p>I think I'm observing the .NET JIT compiler not inlining or optimizing away calls to empty static methods that have no side effects, which is a bit surprising given some bespoken online resources.</p>
  
  <p>My environment is Visual Studio 2013 on x64, Windows 8.1, .NET Framework 4.5.</p>
  
  <p>Given this simple test program (<a href="https://ideone.com/2BRCpC" rel="noreferrer">https://ideone.com/2BRCpC</a>)</p>
  
  <pre><code>class Program
  {
      static void EmptyBody()
      {
      }
  
      static void Main()
      {
          EmptyBody();
      }
  }
  </code></pre>
  
  <p>A release build with optimizations of the above program produces the following MSIL for <code>Main</code> and <code>EmptyBody</code>:</p>
  
  <pre><code>.method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    // Code size       6 (0x6)
    .maxstack  8
    IL_0000:  call       void Program::EmptyBody()
    IL_0005:  ret
  } // end of method Program::Main
  
  .method private hidebysig static void  EmptyBody() cil managed
  {
    // Code size       1 (0x1)
    .maxstack  8
    IL_0000:  ret
  } // end of method Program::EmptyBody
  </code></pre>
  
  <p>It's not surprising that the MSIL contains a call from <code>Main</code> to <code>EmptyBody</code>, since the C# compiler isn't expected to inline or optimize away calls like that. However, I thought that the JIT compiler would then inline or optimize away that call. But that doesn't seem to happen.</p>
  
  <p>If I run the above program and break into the debugger in <code>Main</code>, the generated assembly is this:</p>
  
  <pre><code>00572621  mov         ebp,esp  
  00572623  cmp         dword ptr ds:[4320B84h],0  
  0057262A  je          00572631  
  0057262C  call        73E6AF20  
  00572631  call        dword ptr ds:[4321578h]  
  </code></pre>
  
  <p>The instruction pointer is immediately set to the last line at 00572631, which is the call to <code>EmptyBody</code>. Stepping into <code>EmptyBody</code>, the generated assembly is found to be</p>
  
  <pre><code>00BD2651  mov         ebp,esp  
  00BD2653  cmp         dword ptr ds:[4B00B84h],0  
  00BD265A  je          00BD2661  
  00BD265C  call        73E6AF20  
  00BD2661  nop  
  00BD2662  pop         ebp  
  00BD2663  ret
  </code></pre>
  
  <p>The instruction pointer is immediately set to the <code>nop</code> line at 00BD2661, which doesn't do anything, and I cannot guess why it's generated in the first place.</p>
  
  <p>Given that the two assembly snippets above share the same 4-instruction header, I assume that's just the regular method entry boiler plate where the stack and such is set up. I'm keen to learn to know what these recurring instructions would do, though:</p>
  
  <pre><code>00BD2653  cmp         dword ptr ds:[4B00B84h],0  
  00BD265A  je          00BD2661  
  00BD265C  call        73E6AF20  
  </code></pre>
  
  <p><strong>Anyhow, the main question is: Why does the JIT compiler produce assembly that calls the empty-bodied static method <code>EmptyBody</code>?</strong></p>