3

I have the following line in a function to count the number of 'G' and 'C' in a sequence:

count += (seq[i] == 'G' || seq[i] == 'C');

Are compilers smart enough to do nothing when they see 'count += 0' or do they actually lose time 'adding' 0 ?

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
PhDP
  • 387
  • 3
  • 10
  • 4
    Don't rely on the implicit conversion to `int`, at least say `count += (condition) ? 1 : 0;`. Better even, `if (condition) ++count;`. – Kerrek SB Oct 11 '11 at 02:32
  • When you say 'don't rely', is it performance-wise or just a question of style/clarity ? – PhDP Oct 11 '11 at 02:34
  • 3
    @KerrekSB: why not? its in the standard: http://stackoverflow.com/questions/5369770/bool-to-int-conversion – Daniel Oct 11 '11 at 02:34
  • 3
    @Dani: Because it's obscurant and doesn't make clear to the reader what you're trying to do. Adding the explicit 0 and 1 doesn't change the compilate, but everyone will thank you for it. – Kerrek SB Oct 11 '11 at 02:42
  • 1
    @Dani: All that is allowable is not proper. This is a rule that can be applied to many different topics. – Michael Price Oct 11 '11 at 03:29

5 Answers5

7

Generally

x += y;

is faster than

if (y != 0) { x += y; }

Even if y = 0, because there is no branch in the first option. If its really important, you'll have to check the compiler output, but don't assume your way is faster because it sometimes doesn't do an add.

Clinton
  • 22,361
  • 15
  • 67
  • 163
  • -1. This is not a case of `x += y` where y is an integer though. y is a boolean value. Idiomatically it would be better to write `if (y) { x++; }` here because it expresses the intent better, as KerrekSB mentioned in his comment above. – Mike Bailey Oct 11 '11 at 02:54
  • 4
    @Mike: The question was "Are compilers smart enough to do nothing when they see 'count += 0' or do they actually lose time 'adding' 0 ?". He asked about optimization, not style. I agree with your point, but I'm not sure how it answers the question, and I think mine answer does. – Clinton Oct 11 '11 at 03:10
  • I see your point. If you include the point that the boolean is implicitly casted to an int, I'll remove the down vote. (I can't anyway because it's locked for me atm) – Mike Bailey Oct 11 '11 at 03:15
4

Honestly, who cares??

[Edit:] This actually turned out somewhat interesting. Contrary to my initial assumption, in unoptimized compilation, n += b; is better than n += b ? 1 : 0;. However, with optimizations, the two are identical. More importantly, though, the optimized version of this form is always better than if (b) ++n;, which always creates a cmp/je instruction. [/Edit]

If you're terribly curious, put the following code through your compiler and compare the resulting assembly! (Be sure to test various optimization settings.)

int n;
void f(bool b) { n += b ? 1 : 0; }
void g(bool b) { if (b) ++n;     }

I tested it with GCC 4.6.1: With g++ and with no optimization, g() is shorter. With -O3, however, f() is shorter:

g():                            f():
    cmpb    $0, 4(%esp)              movzbl  4(%esp), %eax
    je      .L1                      addl    %eax, n
    addl    $1, n
  .L1:
    rep

Note that the optimization for f() actually does what you wrote originally: It literally adds the value of the conditional to n. This is in C++ of course. It'd be interesting to see what the C compiler would do, absent a bool type.

Another note, since you tagged this C as well: In C, if you don't use bools (from <stdbool.h>) but rather ints, then the advantage of one version over the other disappears, since both now have to do some sort of testing.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    The assembly will tell you whether it's skipping the add, but it won't tell you if that's faster. – Mark Ransom Oct 11 '11 at 02:44
  • Kerrek: Could you post both `f()` and `g()` at no optimization and -O3? I'm surprised that gcc doesn't compile these the same at `-03`. – Clinton Oct 11 '11 at 02:44
  • @Clinton: it's a bit long... is pastebin OK? – Kerrek SB Oct 11 '11 at 02:48
  • I wonder if this is different in C, since in this optimization the C++ compiler can just assume that `4(%esp)` is precisely either 0 or 1. – Kerrek SB Oct 11 '11 at 02:48
  • @Clinton: OK, I ended up just pasting it here. I removed the common standard opening and ending code. – Kerrek SB Oct 11 '11 at 02:54
  • @Kerrek SB: Oh, the f() and g() you originally posted both were optimised. I thought one wasn't and one was. No need for the un-optimised versions. – Clinton Oct 11 '11 at 03:07
  • @Clinton: I added a note at the top. Turns out that if you don't have optimizations, then the OP's version is actually better than the readable version with the ternary that I suggested. It's only *with* optimizations that both become better than the `if` version. – Kerrek SB Oct 11 '11 at 03:12
2

It depends on your compiler, its optimization options that you used and its optimization heuristics. Also, on some architectures it may be faster to add than to perform a conditional jump to avoid the addition of 0.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
2

Compilers will NOT optimize away the +0 unless the expression on the right is a compiler const value equaling zero. But adding zero is much faster on all modern processors than branching (if then) to attempt to avoid the add. So the compiler ends up doing the smartest thing available in the given situation- simply adding 0.

VoidStar
  • 5,241
  • 1
  • 31
  • 45
1

Some are and some are not smart enough. its highly dependent on the optimizer implementation.
The optimizer might also determine that if is slower than + so it will still do the addition.

Daniel
  • 30,896
  • 18
  • 85
  • 139