I can replicate this behavior on Windows 7, .Net 4.5, Visual Studio 2012, x64 target, Release mode with debugger attached, but “Suppress JIT optimization on module load” disabled. This seems to be a bug in the tail call optimization (which is why you're getting it only on x64).
IL does not really matter here, the native code does. The relevant part of code for GetMonthDiffrence()
is:
0000005e cmp rdx,rcx
00000061 setg al
00000064 movzx eax,al
00000067 test eax,eax
00000069 je 0000000000000081 // else branch
0000006b mov rax,qword ptr [rsp+68h]
00000070 mov qword ptr [rsp+60h],rax
00000075 mov rax,qword ptr [rsp+60h]
0000007a mov qword ptr [rsp+68h],rax
0000007f jmp 0000000000000012 // start of the method
The important part are the 4 mov
instructions. They try to exchange [rsp+68h]
and [rsp+60h]
(which is where the parameters are stored), but they do it incorrectly, so both end up with the same value.
Interestingly, if I remove the call to Console.ReadKey()
from your Main()
, the code works fine, because the call to GetMonthDiffrence()
is inlined and the tail call optimization is not performed in that case.
A possible workaround would be to add [MethodImpl(MethodImplOptions.NoInlining)]
to your method, that seems to disable the tail call optimization.
I have submitted this bug on Connect.