views:

53

answers:

2

Hi,

The following C#-snippet:

var x = 1;
var y = 1;
if (x == y)
    Console.Write("True");

Generates this MSIL:

.locals init (
            [0] int32 x,
            [1] int32 y,
            [2] bool CS$4$0000)
L_0000: nop 
L_0001: ldc.i4.1 
L_0002: stloc.0 
L_0003: ldc.i4.1 
L_0004: stloc.1 
L_0005: ldloc.0 
L_0006: ldloc.1 
L_0007: ceq 
L_0009: ldc.i4.0 
L_000a: ceq 
L_000c: stloc.2 
L_000d: ldloc.2 
L_000e: brtrue.s L_001b
L_0010: ldstr "True"
L_0015: call void [mscorlib]System.Console::Write(string)
L_001a: nop 
L_001b: ret 

Why is there two ceq calls?

Thanks

+2  A: 

The second ceq opcode compares the result of the first one to 0. (false)

This result is then put in a variable, loaded from the variable, and, if it was true, the WriteLine call is skipped.

I would assume that Release mode generates more efficient code, but I'm too lazy to check.

SLaks
Yes, from what i can tell, release mode generates more efficent il-code. There is not even a call to `ceq`. Is this because the compiler knows that x and z are constants?
alexn
@alexn: Correct. The compiler optimizes out the constant comparisons. If you don't want it to, you can write `Math.Max(1, 1)`, which is not a compile-time constant.
SLaks
+2  A: 

About comparing values with ceq From MSDN:

If they are equal, the integer value 1 (int32) is pushed onto the evaluation stack; otherwise 0 (int32) is pushed onto the evaluation stack.

The second ceq checks whether the first comparison failed, if so, it jumps to the exit point.

Saulius
Thanks for your answer.
alexn