boolean test

For bool b, is the test if (b) slightly faster than if (!b)? For example, should I change code

if (!b) do_a();
else do_b();

into

if (b) do_b();
else do_a();
?
Or will they be compiled (optimized) to the same thing?
It depends on whether the code is optimized or not during compilation.

https://stackoverflow.com/questions/5764956/which-is-faster-if-bool-or-ifint

Modern compilers are quite good at generating machine code that is efficient.

FYI....using code tags to format your code snippets will go a long way in showing you are serious about accepting help.

PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

HINT: you can edit your post and add code tags.

Some formatting & indentation would not hurt either
> Or will they be compiled (optimized) to the same thing?
The best thing you can do with modern compilers is to stop thinking of them as dumb machines that literally transcribe your code into assembler.

That might have been true in the 1970's, but it isn't any more.

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Your chance of beating the compiler on a consistent basis is basically zero.

Do the jobs you're supposed to be doing, and leave the compiler to the jobs it's good at.

Your job being:

- coming up with a design that will solve the problem.
Because compilers can't design anything.

- choosing the most appropriate algorithms and data structures.
Because no compiler will ever fix your broken choice of bubble sort by replacing it with quicksort.

- writing clean, easy to understand (by humans) code.
The nanosecond you might save by trying to be clever with just one if
statement will never be offset by the days spent by the next programmer
(possibly yourself) staring at the code and wondering what the F were
you smoking when you wrote it.

Unless your design tells you this is important, then it isn't important.


Premature optimisation - https://ubiquity.acm.org/article.cfm?id=1513451
Remember the 80/20 rule applies here.
80% of the time, you'll only be using 20% of the code.
If your code isn't in that 20% (you profiled it right), it isn't worth the time to think about.

Bike shedding - https://thedecisionlab.com/biases/bikeshedding
Everyone loves a good if/else optimisation story.
Every dog has an opinion about it, and it's easy to understand.
But it completely misses the bigger picture.
Last edited on
Compiler Explorer is useful when you have questions like this.

https://godbolt.org/z/vGoMh6jTz <-- GCC with -O2 (very very similar)
https://godbolt.org/z/o8KvPoxvb <-- Clang with -O2 (exactly the same)
Last edited on
If production code is 'running too slow' then profile to see where are the bottle necks. Then concentrate attention on those areas - and in particular the algorithm(s) used. Using a 'better performance' algorithm usually has a much more marked improvement than micro-tinkering with code. Make sure you're not doing unnecessary object copies. if you really want to get into micro-management then you need to do statistically analysis of the probability of which branch will be taken. The least probable should be branched so the most probable doesn't disrupt the pipeline. https://en.wikipedia.org/wiki/Branch_predictor
C++20 also supports the [[likely]] and [[unlikely]] attributes.

https://learn.microsoft.com/en-us/cpp/cpp/attributes?view=msvc-170
Visual Studio 2019 version 16.6 and later: (Available with /std:c++20 and later.) The [[likely]] attribute specifies a hint to the compiler that the code path for the attributed label or statement is more likely to execute than alternatives. In the Microsoft compiler, the [[likely]] attribute marks blocks as "hot code", which increments an internal optimization score. The score is incremented more when optimizing for speed, and not as much when optimizing for size. The net score affects the likelihood of inlining, loop unrolling, and vectorizing optimizations. The effect of [[likely]] and [[unlikely]] is similar to Profile-guided optimization, but limited in scope to the current translation unit. The block reordering optimization isn't implemented yet for this attribute.

Example at: https://en.cppreference.com/w/cpp/language/attributes/likely
Last edited on
I had no idea that using those two C++20 attributes would make a difference like that, I thought using them (and others) was simply a "document the code" feature.

I see that C23 now has attribute specifier sequences, likely borrowed from C++. Sweet!
I think its going to depend on the hardware, but not much. Most hardware gonna have jump if zero type instruction. It costs the same either way.

Since the invention of branch prediction, its very, very challenging to optimize branches but the first thing you can do, always, that works every time, is to eliminate a branch entirely where you can (and when you need to, too much of this quickly becomes unreadable nonsense and is overkill and horrible). If the code does not branch, it won't branch in the assembler either, and if it doesn't branch, the branch predictor can't fail and you can't have unnecessary context switches or cache misses or other similar performance hits that are incurred when you jump in the code.

An example of this:
if(x)
x++;
else
x = 42;

can be re-written to
const bool b = (x!=0); //bool in c++ is 0 or 1 numerically and you can use it as such.
x = (x+1)*b + 42*(!b);
its ugly, but this can't accidentally jump.

also, its is almost always faster to do nothing or next to nothing than to branch. So derpy code like
for(x = 0; x<somegiantvalue; x++)
if(x) y+= x;
is almost always slower than just saying y+=x, even with branch prediction -- only if the compiler can recognize the issue and rewrite it for you will it be equal. It costs more to check if x is zero than to add zero to a number.

Most of this stuff really only matters for high performance but very simple code where its easy to refactor it around the jumps. And with the speed of today's processors, its getting hard and harder to justify weirdness in most code.
Last edited on
I don't think we can say in general which is "faster". If there is any difference at all, the speedier choice surely depends on the computer, compiler, and the rest of the code.

From a style perspective, consider if (my_boolean) do_a(); else do_b(); because it may be easier to understand a condition that is not negated. This is more true as the condition gets more complicated.

For instance, compare:
if (! is_not_frobnicated) do_a(); else do_b();
with
if (is_not_frobnicated) do_b(); else do_a();
with
if (is_frobnicated) do_a(); else do_b();

Obviously this has to be balanced against competing concerns.
Last edited on
Topic archived. No new replies allowed.