dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.9k stars 4.01k forks source link

Elvis operator and comparison of nullable result with non nulable constant #25543

Open omariom opened 6 years ago

omariom commented 6 years ago

Version Used:

2.3.2

Steps to Reproduce:

Version with elvis opeator

Simple version

Expected Behavior:

I expect both versions to generate the same IL and as the result the same machine code.

Actual Behavior:

The generated IL is different. The version with elvis operator is less efficient.

gafter commented 6 years ago

How much difference do you see in the machine code that is executed at runtime?

omariom commented 6 years ago

The generated code is identical on .NET Core 2.0 x64.

On .NET Framework 4.6.2 x64 elvis adds and eax,0FFh

Simple:

 sub         rsp,28h  
 test        rcx,rcx  
 je          000007FE98790687  
 mov         rax,rcx  
 mov         rcx,qword ptr [rax+8]  
 call        qword ptr [rax+18h]  
 test        al,al  
 je          000007FE98790691  
 mov         eax,3  
 add         rsp,28h  
 ret  
 mov         eax,7  
 add         rsp,28h  
 ret

Elvis:

 sub         rsp,28h  
 test        rcx,rcx  
 je          000007FE987806EC  
 mov         rax,rcx  
 mov         rcx,qword ptr [rax+8]  
 call        qword ptr [rax+18h]  
 and         eax,0FFh  ; <<<<<<<<<<<<<<<<<<<<<<<<
 test        eax,eax  
 je          000007FE987806F6  
 mov         eax,3  
 add         rsp,28h  
 ret  
 mov         eax,7  
 add         rsp,28h  
 ret

A bit more on 4.6.2 x32 - mov and jmp

Simple:

 push        ebp  
 mov         ebp,esp  
 test        ecx,ecx  
 je          004005D3  
 mov         eax,dword ptr [ecx+0Ch]  
 mov         ecx,dword ptr [ecx+4]  
 call        eax  
 test        eax,eax  
 je          004005DA  
 mov         eax,3  
 pop         ebp  
 ret  
 mov         eax,7  
 pop         ebp  

Elvis:

 push        ebp  
 mov         ebp,esp  
 test        ecx,ecx  
 jne         0040062E  
 mov         eax,1           ; <<<<<<<<<<<<<<<<<<<<<<
 jmp         00400636        ; <<<<<<<<<<<<<<<<<<<<<<
 mov         eax,dword ptr [ecx+0Ch]  
 mov         ecx,dword ptr [ecx+4]  
 call        eax  
 test        eax,eax  
 je          00400641  
 mov         eax,3  
 pop         ebp  
 ret  
 mov         eax,7  
 pop         ebp  
 ret
gafter commented 6 years ago

Yes, I can see the code is a tiny bit different on 4.6.2 and the same on core.