Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler Magic: Why?

I just noticed that given the following code:

if (x.ID > 0 && !x.IsCool)

the Microsoft C# 3.0 (VS2008 SP1) compiler will optimize it to this:

if (!((x.Id <= 0) || x. IsCool))

This is on Debug build without Optimization enabled. Why does the compiler do that? Is it faster in terms of execution?

I used Reflector to find that out (I was actually looking for something different)

like image 499
Johannes Rudolph Avatar asked Nov 03 '09 21:11

Johannes Rudolph


2 Answers

The C# compiler certainly does not generate an equivalent C# code for your snippet. It's compiled down to IL. Basically, what you are seeing (from Reflector, I guess) is the equivalent C# code that a decompiler spits out for that IL.

  1. The language specification does not say what an "unoptimized" code is. The C# compiler is allowed to generate any valid, functionally equivalent code. Even without optimization switch on, the compiler might do basic optimizations. Beside that, you can't say what is natural for the compiler and whether the compiler deliberately optimized it or not.

  2. The if statement as a whole is evaluated as a sequence of conditional branches based on the values of each individual expression specified in the "and" clause. The expression is not evaluated in a single code block with "and" instructions. The output of the decompiler is something inferred from those branches. The decompiler cannot always infer the original expression you wrote. It just outputs something equivalent.

Similarly, the difference between this snippet:

if (a) { something(); }
else { somethingElse(); }

and this snippet:

if (!a) { somethingElse(); }
else { something(); }

is not something you'd distinguish by seeing the compiled code.

like image 153
mmx Avatar answered Oct 12 '22 23:10

mmx


I think these two expressions are exactly equivalent from a language semantics point of view. Both ways involve short-circuiting.

I am kind of flabbergasted that Andrew's answer already has ten upvotes; it sounds like nonsense to me, but perhaps I really am missing something subtle here.

EDIT

So just to sum up:

The OP's question asks "why does this optimization happen".

In fact there's no 'optimization' happening. The two C# source codes are logically equivalent. ".Net Reflector" or whatever other disassembly tool is perhaps as likely to decompile the same IL into one or the other. At the IL level, there's just a bunch of conditional jumps, and so there's not necessarily a way to know "which way is if and which is else" or other similar DeMorgan equivalences.

Fascinatingly, people are wildly happy to vote up or down answers to this question, even when (or perhaps because) the original question does not make much sense (or relies on a faulty assumption).

Happily, eventually the wisdom of the crowds (and smart individuals like @Mehrdad) prevails. Hurray for StackOverflow!

(I am making my answer a wiki, because I don't want rep for "storytelling about a question" when rep should be awarded to "good answers to a question". But I think the story of this question is interesting.)

like image 32
2 revs Avatar answered Oct 12 '22 23:10

2 revs