NominSim
NominSim

Reputation: 8511

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.

Upvotes: 4

Views: 870

Answers (3)

Steve Czetty
Steve Czetty

Reputation: 6228

No, the complier will not optimize it in my experience, however, you can do:

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

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500675

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.

Upvotes: 7

Nikhil Agrawal
Nikhil Agrawal

Reputation: 48568

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.

It will calculate the value each time.

What if this was a multi-threaded application. Some other thread might change it.

If they are not constant variables, they can be changed.

To optimise you can do

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

In this case it will be calculated once and value assigned first to AnotherButton first and SomeButton later. Remember its right to left in assignment.

Upvotes: 4

Related Questions