1

Specifically, I am asking about the double '!' in the params of the __built_in.

Is it a double negation, per the 'C' language?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
user3342339
  • 349
  • 1
  • 5
  • 19
  • 4
    It can be used to convert any value into a boolean 0 or 1. Ex. `!!(42) == 1` – Colonel Thirty Two Jul 28 '14 at 16:10
  • Related: http://stackoverflow.com/questions/7346929/why-do-we-use-builtin-expect-when-a-straightforward-way-is-to-use-if-else – Mihai Todor Jul 28 '14 at 16:10
  • `if(x)` and `if (__builtin_expect(!!(x), 1))` should reproduce the same order in generated code. Whoever wrote this is doing premature optimization wrong. – Havenard Jul 28 '14 at 16:13
  • 1
    @Havenard actually, it's an optimization for branch prediction. It's saying that `x` is more than likely non-zero, but it might not be. If it's part of a frequently-checked conditional, the extra performance from successful branch prediction can be substantial. – Drew McGowen Jul 28 '14 at 16:15
  • Yes but if it is likely to be non-zero, then `if(x)` will suffice. Looking from assembly perspective the only thing this is doing is converting `x` to either 0 or 1 before `test x,x` instead of doing `test x,x` straight on. May be even inducing the compiler to use `cmp x,1` instead, which is worse. – Havenard Jul 28 '14 at 16:22
  • `if(x)` is a generic test for whether or not `x` is zero. The compiler makes no assumptions as to which value is more likely, thus it must rely on dynamic branch prediction, and may incorrectly guess the first few iterations. However, using `__builtin_expect` will insert a *hint* as to what the initial guess for the branch prediction should be. – Drew McGowen Jul 28 '14 at 16:23
  • Yes it makes no assumption and just generates the code the order you wrote it, with the block for non-zero first, just like this `__builtin_expect` case would do. – Havenard Jul 28 '14 at 16:31
  • I'm not saying `__builtin_expect` is useless, I'm just saying it is not fulfilling its purpose in this particular case. – Havenard Jul 28 '14 at 16:32

1 Answers1

4

The !! is simply two ! operators right next to each other. It's a simple way of converting any non-zero value to 1, and leaving 0 as-is. (Aka "booleanize" the value). See !! c operator, is a two NOT? for more discussion of the logical operator in general, outside the context of __builtin_expect.

Why we want !!(x) for __builtin_expect

We want to tell the compiler that x is likely to be non-zero, not that x is likely to be exactly 1. It's the difference between telling the compiler to expect x != 0 vs. x == 1, which might matter for other code in the same function.

We could equivalently have written __builtin_expect( (x)!=0, 1 ).

The second arg of __builtin_expect is a value the compiler should expect the first expression to be equal to. This is not restricted to booleans; see How far does GCC's __builtin_expect go? for uses of expected values other than 0 or 1.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Drew McGowen
  • 11,471
  • 1
  • 31
  • 57
  • Thus, it is superfluous in the example (a boolean context). – Deduplicator Jul 28 '14 at 16:50
  • 2
    It's necessary for the given `__builtin_expect`, because it takes two values that are expected to be equal. If it was just `if(x)`, then yes, it would be superfluous. – Drew McGowen Jul 28 '14 at 18:10
  • Say that to the Linux kernel guys: http://stackoverflow.com/questions/109710/likely-unlikely-macros-in-the-linux-kernel Though it looks like they added that later too... – Deduplicator Jul 28 '14 at 20:19