I don't know why but I watched the IL generated from the standard c# compiler (VS2015) and it's dramatically non optimized in release mode.
The code that I tested is very simple:
static void Main(string[] args)
{
int count = 25 + 7/3;
count += 100;
Console.WriteLine("{0}", count);
}
The IL output in debug mode is:
// [12 9 - 12 10]
IL_0000: nop
// [34 13 - 34 34]
IL_0001: ldc.i4.s 27 // 0x1b
IL_0003: stloc.0 // count
// [35 13 - 35 26]
IL_0004: ldloc.0 // count
IL_0005: ldc.i4.s 100 // 0x64
IL_0007: add
IL_0008: stloc.0 // count
// [36 13 - 36 45]
IL_0009: ldstr "{0}"
IL_000e: ldloc.0 // count
IL_000f: box [mscorlib]System.Int32
IL_0014: call void [mscorlib]System.Console::WriteLine(string, object)
IL_0019: nop
// [37 9 - 37 10]
IL_001a: ret
and the code in Release mode is:
IL_0000: ldc.i4.s 27 // 0x1b
IL_0002: stloc.0 // V_0
IL_0003: ldloc.0 // V_0
IL_0004: ldc.i4.s 100 // 0x64
IL_0006: add
IL_0007: stloc.0 // V_0
IL_0008: ldstr "{0}"
IL_000d: ldloc.0 // V_0
IL_000e: box [mscorlib]System.Int32
IL_0013: call void [mscorlib]System.Console::WriteLine(string, object)
IL_0018: ret
Now, Why the compiler are not perform the sum (27 + 100) and direct call WriteLine with 127 ?
I tried the same sample in c++ and it works as expected.
There's some special flag to perform this kind optimization?
UPDATE: I try the same code on MONO 4.6.20 and the result in release mode is the following
// method line 2
.method private static hidebysig
default void Main (string[] args) cil managed
{
// Method begins at RVA 0x2058
.entrypoint
// Code size 18 (0x12)
.maxstack 8
IL_0000: ldstr "{0}"
IL_0005: ldc.i4.s 0x7f
IL_0007: box [mscorlib]System.Int32
IL_000c: call void class [mscorlib]System.Console::WriteLine(string, ob ject)
IL_0011: ret
} // end of method Program::Main
You can't rely on the IL output of the compiler to accurately assess how optimized the code is, because the JIT is going to get its hand on the IL at runtime to generate the actual code to run. In this case the actual x64 emitted by the JIT (in Release mode for Any CPU without Prefer 32-bit) looks like this:
sub rsp,28h
mov rcx,7FFF85323E98h
call 00007FFF91C72530 ; I'm not sure what this call does, I assume it's allocating memory for the boxed int
mov rcx,20CA5CB3648h
mov rcx,qword ptr [rcx] ; After this rcx is actually pointing to the string "{0}"
mov dword ptr [rax+8],7Fh ; Box the value 127 into the object that rax points at
mov rdx,rax
call 00007FFF85160070 ; Call Console.WriteLine with its arguments in rcx and rdx
nop
add rsp,28h
ret
So the extra edition gets elided.
If I turn on "Prefer 32-bit", the emitted x86 looks like this:
mov ecx,72041638h
call 011630F4 ; presumably allocating memory for the boxed int
mov edx,eax
mov eax,dword ptr ds:[40E232Ch] ; loads a pointer to "{0}" into eax
mov dword ptr [edx+4],7Fh ; boxes 127 into object pointed at by edx
mov ecx,eax
call 71F373F4 ; calls Console.WriteLine with arguments in ecx and edx
ret
In both cases the JIT optimized out the local variable as well as the extra addition operations. Since the JIT performs so many optimizations, you'll find that the C# compiler itself doesn't go to great lengths to optimize anything.
tl;dr The emitted IL from the C# compiler is not what the machine runs and so is not generally representative of the sorts of optimizations will be applied.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.