Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8995759
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T23:39:45+00:00 2026-06-15T23:39:45+00:00

In removing conditional branches from high-performance code, converting a true boolean to unsigned long

  • 0

In removing conditional branches from high-performance code, converting a true boolean to unsigned long i = -1 to set all bits can be useful.

I came up with a way to obtain this integer-mask-boolean from input of a int b (or bool b) taking values either 1 or 0:

unsigned long boolean_mask = -(!b);

To get the opposite value:

unsigned long boolean_mask = -b;

Has anybody seen this construction before? Am I on to something? When a int value of -1 (which I assume -b or -(!b) does produce) is promoted to a bigger unsigned int type is it guaranteed to set all the bits?

Here’s the context:

uint64_t ffz_flipped = ~i&~(~i-1); // least sig bit unset
// only set our least unset bit if we are not pow2-1
i |= (ffz_flipped < i) ? ffz_flipped : 0;

I will inspect the generated asm before asking questions like this next time. Sounds very likely the compiler will not burden the cpu with a branch here.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T23:39:45+00:00Added an answer on June 15, 2026 at 11:39 pm

    The question you should be asking yourself is this: If you write:

    int it_was_true = b > c;
    

    then it_was_true will be either 1 or 0. But where did that 1 come from?

    The machine’s instruction set doesn’t contain an instruction of the form:

    Compare R1 with R2 and store either 1 or 0 in R3
    

    or, indeed, anything like that. (I put a note on SSE at the end of this answer, illustrating that the former statement is not quite true.) The machine has an internal condition register, consisting of several condition bits, and the compare instruction — and a number of other arithmetic operations — cause those condition bits to be modified in specific ways. Subsequently, you can do a conditional branch, based on some condition bits, or a conditional load, and sometimes other conditional operations.

    So actually, it could be a lot less efficient to store that 1 in a variable than it would have been to have directly done some conditional operation. Could have been, but maybe not, because the compiler (or at least, the guys who wrote the compiler) may well be cleverer than you, and it might just remember that it should have put a 1 into it_was_true so that when you actually get around to checking the value, the compiler can emit an appropriate branch or whatever.

    So, speaking of clever compilers, you should take a careful look at the assembly code produced by:

    uint64_t ffz_flipped = ~i&~(~i-1);
    

    Looking at that expression, I can count five operations: three bitwise negations, one bitwise conjunction (and), and one subtract. But you won’t find five operations in the assembly output (at least, if you use gcc -O3). You’ll find three.

    Before we look at the assembly output, let’s do some basic algebra. Here’s the most important identity:

    -X == ~X + 1
    

    Can you see why that’s true? -X, in 2’s complement, is just another way of saying 2n - X, where n is the number of bits in the word. In fact, that’s why it’s called “2’s complement”. What about ~X? Well, we can think of that as the result of subtracting every bit in X from the corresponding power of 2. For example, if we have four bits in our word, and X is 0101 (which is 5, or 22 + 20), then ~X is 1010 which we can think of as 23×(1-0) + 22×(1-1) + 21×(1-0) + 20×(1-1), which is exactly the same as 1111 − 0101. Or, in other words:

     −X == 2n − X

      ~X == (2n−1) − X
    which means that

      ~X == (−X) − 1

    Remember that we had

    ffz_flipped = ~i&~(~i-1);
    

    But we now know that we can change ~(~i−1) into minus operations:

    ~(~i−1)

    == −(~i−1) − 1

    == −(−i - 1 - 1) − 1

    == (i + 2) - 1

    == i + 1

    How cool is that! We could have just written:

    ffz_flipped = ~i & (i + 1);
    

    which is only three operations, instead of five.

    Now, I don’t know if you followed that, and it took me a bit of time to get it right, but now let’s look at gcc’s output:

        leaq    1(%rdi), %rdx     # rdx = rdi + 1 
        movq    %rdi, %rax        # rax = rdi                                        
        notq    %rax              # rax = ~rax                             
        andq    %rax, %rdx        # rdx &= rax
    

    So gcc just went and figured all that out on its own.


    The promised note about SSE: It turns out that SSE can do parallel comparisons, even to the point of doing 16 byte-wise comparisons at a time between two 16-byte registers. Condition registers weren’t designed for that, and anyway no-one wants to branch when they don’t have to. So the CPU does actually change one of the SSE registers (a vector of 16 bytes, or 8 “words” or 4 “double words”, whatever the operation says) into a vector of boolean indicators. But it doesn’t use 1 for true; instead, it uses a mask of all 1s. Why? Because it’s likely that the next thing the programmer is going to do with that comparison result is use it to mask out values, which I think is just exactly what you were planning to do with your -(!B) trick, except in the parallel streaming version.

    So, rest assured, it’s been covered.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am having problems removing index.php from codeigniter-2. I remember using the same code
Removing annotations from my map view in the following way: if ([[self.mapView annotations] count]
For removing trailing part is I use the code str.substring(0,str.length -2) Is there a
After removing hash from URL using window.location.hash='' page getting reloaded in firefox. EDIT Example:
I am removing all non-numeric and non-decimal values using: Regex.Replace(A1B2C3.D4E5F6.G7H8I9, @[^-?\d+\.], ); Output: 123.456.789
In IE8 when dynamically removing TR elements from a table inside a DIV with
We're looking at removing all of the static resources (mainly images) in our ASP.NET
The following code snippet is from book Effective C#, public event AddMessageEventHandler Log; public
I'm looking for a method - if at all possible - of removing a
EDIT: SOLVED! I added BOOST_ALL_NO_LIB to my Conditional defines and added the errorcode.cpp from

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.