Perhaps a Wikipedia article on Boolean algebra helps.
A proposal is micro-optimization that can turn a macro into a rush. The just-in-time compiler generates a conditional branch for the if () operator, at least Microsoft-created ones are not smart enough to optimize the code itself. You will need to look - see if the Mono jitter can do a better job by looking at the generated machine code. Typical code generation is as follows:
if (someBoolVar) anotherBoolVar = true; 00007FFD989F3BB1 movzx eax,cl 00007FFD989F3BB4 test eax,eax 00007FFD989F3BB6 je 00007FFD989F3BBA // <=== here 00007FFD989F3BB8 mov dl,1 00007FFD989F3BBA etc...
Conditional branches, such as the JE command in the above machine code, are complex for a modern processor; it relies heavily on the pipeline to make the code run quickly. The generation of commands and the generation of micro-operations are performed in advance. It is also very important for the prefisher, he tries to guess which memory cells should be available in the caches, so the execution mechanism does not stop when the contents of the memory are required. The memory is very, very slow compared to the raw processor speed.
The processor has a branch predictor, it keeps track of whether a branch was taken when previously executed code. And assumes that the branch will behave the same again. If he suspects what is wrong, the pipeline needs to be cleaned. A lot of work is thrown away and the processor will stand while it is filling. Extra long stalls can occur if the picker guessed that it was. There is a good SO publication that explains the consequences of incorrect prediction.
Using Boolean algebra excludes a branch, it will generate an OR or AND instruction, they take one cycle and can never clear the pipeline. Of course, micro-optimization, it turns into a macro only when this code is inside ~ 10% of your code, which determines the speed of your program. The IDE will not be smart enough to tell you if it could be, only the profiler can show you this.
Fwiw, there are more such micro-optimizations, programmers tend to use && and || operators improperly. The short-circuited behavior of these operators always requires a machine code branch. This behavior is not always necessary, usually it is not, but the and and | the operator can generate much faster code. If the left operand is poorly predicted, it can make the code 500% slower.
Hans passant
source share