Roslyn compiler optimizing away function call multiplication with zero : <p>Yesterday I found this strange behavior in my C# code:</p>

<pre><code>Stack&lt;long&gt; s = new Stack&lt;long&gt;();

s.Push(1);           // stack contains [1]
s.Push(2);           // stack contains [1|2]
s.Push(3);           // stack contains [1|2|3]

s.Push(s.Pop() * 0); // stack should contain [1|2|0]

Console.WriteLine(string.Join("|", s.Reverse()));
</code></pre>

<p>I assumed the program would print <code>1|2|0</code> but in fact it printed <code>1|2|3|0</code>.</p>

<p>Looking at the generated IL code (via ILSpy) you can see that <code>s.Pop() * 0</code> is optimized to simply <code>0</code>:</p>

<pre><code>// ...
IL_0022: ldloc.0
IL_0023: ldc.i4.0
IL_0024: conv.i8
IL_0025: callvirt instance void class   [System]System.Collections.Generic.Stack`1&lt;int64&gt;::Push(!0)
// ...
</code></pre>

<p><em>ILSpy decompilation</em>:</p>

<pre><code>Stack&lt;long&gt; s = new Stack&lt;long&gt;();
s.Push(1L);
s.Push(2L);
s.Push(3L);
s.Push(0L); // &lt;- the offending line
Console.WriteLine(string.Join&lt;long&gt;("|", s.Reverse&lt;long&gt;()));
</code></pre>

<p>First I tested this initially under Windows 7 with Visual Studio 2015 Update 3 with both Release mode (<code>/optimize</code>) and Debug mode and with various target frameworks (4.0, 4.5, 4.6 and 4.6.1). In all 8 cases the result was the same (<code>1|2|3|0</code>).</p>

<p>Then I tested it under Windows 7 with Visual Studio 2013 Update 5 (again with all the combinations of Release/Debug mode and target framework). To my surprise the statement is here <em>not</em> optimized away and yields the expected result <code>1|2|0</code>.</p>

<p>So I can conclude that this behavior is neither dependent on <code>/optimize</code> nor the target framework flag but rather on the used compiler version.</p>

<p>Out of interest I wrote a similar code in C++ and compiled it with the current gcc version. Here a function call multiplied with zero is not optimized away and the function is properly executed.</p>

<p>I think such an optimization would only be valid if <code>stack.Pop()</code> were a pure function (which it definitely isn't). But I'm hesitant to call this a bug, I assume it's just a feature unknown to me?</p>

<p>Is this "feature" anywhere documented and is there an (easy) way to disable this optimization?</p>
