Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't C# compiler optimize away duplicate local variable default value initialization?

Tags:

c#

clr

il

Background

I know that Compiler would "Omit generating code for things like int foo = 0; for fields Because the memory allocator will initialize fields to default values." Reference

        class Foo
        {
            public int a = 1;
            public int b = 0;
        }
        Foo..ctor:
        IL_0000:  ldarg.0     
        IL_0001:  ldc.i4.1
        IL_0002:  stfld       UserQuery+Foo.a // There is no b.
        IL_0007:  ldarg.0
        IL_0008:  call        System.Object..ctor
        IL_000D:  ret

I also know that "The compiler automatically adds .locals init on every method that uses local variables, indicating JIT must inject the code initializing all local variables before commencing the method execution." Reference

Question

Why doesn't compiler omit generating IL for things like int foo = 0; for local variables since .locals init already cover that? (for consistency with fields?)

(I understand C# spec requires local variable to be definitely assigned, I am ok with that.)

(The link I referenced says the reason why .locals init is needed, and why C# spec requires locals to be initialized. But it doesn't say why additional IL instructions to initialize the default values must exist. As the verification process is assured by .locals init already)

void Main()
{
    int a = 0;
    int b = 1;
    int c = 0;
    int d = a + b + c;
    d++;
}

.maxstack 2
.locals init (int a, int b, int c, int d)

IL_0000:  ldc.i4.0    
IL_0001:  stloc.0     // a (Can be optimized away)
IL_0002:  ldc.i4.1    
IL_0003:  stloc.1     // b
IL_0004:  ldc.i4.0    
IL_0005:  stloc.2     // c (Can be optimized away)
IL_0006:  ldloc.0     // a
IL_0007:  ldloc.1     // b
IL_0008:  add         
IL_0009:  ldloc.2     // c
IL_000A:  add         
IL_000B:  stloc.3     // d
IL_000C:  ldloc.3     // d
IL_000D:  ldc.i4.1    
IL_000E:  add         
IL_000F:  stloc.3     // d
like image 209
colinfang Avatar asked Nov 12 '22 02:11

colinfang


1 Answers

Why doesn't compiler omit generating IL for things like int foo = 0; for local variables since .locals init already cover that?

Why should it? I have not actually verified this, but I would be surprised if the JIT compiler generated different native code if you removed the unnecessary initialization.

What this means is that the only benefit adding this optimization to the C# compiler would have is to make the JIT compilation tiny bit faster (because it would have to process smaller amount of IL code). It seems the authors of the C# compiler though that making this optimization for such a tiny benefit is not worth it.

like image 124
svick Avatar answered Nov 15 '22 00:11

svick