Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will the compiler optimize for boolean assignment?

This is what I want to do:

if(ABoolean || (BBoolean && CBoolean))
{
    SomeButton.Enabled = true;
    AnotherButton.Enabled = true;
}
else 
{
    SomeButton.Enabled = false;
    AnotherButton.Enabled = false;
}

I can switch this to:

SomeButton.Enabled = (ABoolean || (BBoolean && CBoolean));
AnotherButton.Enabled = (ABoolean || (BBoolean && CBoolean));

For a much more succinct code. My question is, does the compiler optimize the assignment such that it will see that the boolean expression is the same and assign its value for the second button, or will it calculate the value each time.

Note: I understand this is a trivial example and that the speedup/slowdown will be minuscule to the point of inconsequentiality, but it will serve to give me a better understanding of compiler optimization.

Edit: Here is the reason why I thought the second option might be optimized:

class Program
{
    static bool ABoolean = true, BBoolean = true, CBoolean = false;
    static bool AEnable, BEnable;


    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < 1000000000; i++)
        {
            Operation1();
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        Stopwatch sw1 = new Stopwatch();
        sw1.Start();
        for (int i = 0; i < 1000000000; i++)
        {
            Operation2();
        }
        sw1.Stop();
        Console.WriteLine(sw1.ElapsedMilliseconds);
        Console.Read();
    }

    static void Operation1()
    {
        if (ABoolean || (BBoolean && CBoolean))
        {
            AEnable = true;
            BEnable = true;
        }
        else
        {
            AEnable = false;
            BEnable = false;
        }
    }

    static void Operation2()
    {
        AEnable = (ABoolean || (BBoolean && CBoolean));
        BEnable = (ABoolean || (BBoolean && CBoolean));
    }
}

This resulted in an approximate ~8-9 second difference over the 1 billion operations (with the second option running faster). As I added more "Enable" booleans in however the second operation became slower.

like image 357
NominSim Avatar asked Dec 12 '22 01:12

NominSim


1 Answers

No, I wouldn't expect the compiler to optimize that. It's possible that the JIT could optimize that (as it has more information) but I wouldn't expect the C# compiler to.

How could the compiler know whether SomeButton.Enabled will have some side-effect which could change the value of ABoolean, BBoolean or CBoolean?

EDIT: Validation of this... let's give the C# compiler the absolute most chance:

class Test
{
    static void Main()
    {
        Foo(true, false, true);
    }

    static void Foo(bool x, bool y, bool z)
    {
        A = x || (y && z);
        B = x || (y && z);
    }

    static bool A { get; set; }
    static bool B { get; set; }
}

Compile with:

csc /o+ /debug- Test.cs

Code for Foo via ILDASM:

.method private hidebysig static void  Foo(bool x,
                                           bool y,
                                           bool z) cil managed
{
  // Code size       37 (0x25)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  brtrue.s   IL_000c
  IL_0003:  ldarg.1
  IL_0004:  brfalse.s  IL_0009
  IL_0006:  ldarg.2
  IL_0007:  br.s       IL_000d
  IL_0009:  ldc.i4.0
  IL_000a:  br.s       IL_000d
  IL_000c:  ldc.i4.1
  IL_000d:  call       void Test::set_A(bool)
  IL_0012:  ldarg.0
  IL_0013:  brtrue.s   IL_001e
  IL_0015:  ldarg.1
  IL_0016:  brfalse.s  IL_001b
  IL_0018:  ldarg.2
  IL_0019:  br.s       IL_001f
  IL_001b:  ldc.i4.0
  IL_001c:  br.s       IL_001f
  IL_001e:  ldc.i4.1
  IL_001f:  call       void Test::set_B(bool)
  IL_0024:  ret
} // end of method Test::Foo

As you can see, the expression really is evaluated in both cases.

like image 68
Jon Skeet Avatar answered Dec 23 '22 15:12

Jon Skeet