Conditionally Set or Clear Bits Without Branching
This article explores techniques for modifying binary bits based on a
condition without using standard conditional jump or branch instructions
(if/else or ternary operators). In
performance-critical software, avoiding branch mispredictions can
significantly improve CPU pipeline efficiency. By leveraging binary
arithmetic, bitwise operators, and two's complement properties, you can
set, clear, toggle, or assign bit states deterministically across
various architectures.
The Fundamental Primitive: Mask Generation
The foundation of branchless bit manipulation relies on converting a
boolean condition (\(0\) for false,
\(1\) for true) into an all-ones
(~0 or -1) or all-zeros (0)
bitmask.
In two's complement arithmetic, negating a boolean integer yields:
-0results in0x00000000(all bits 0)-1results in0xFFFFFFFF(all bits 1)
If your condition c is already normalized to
0 or 1, you can create a full-width mask
using:
mask = -c;1. Conditionally Setting a Specific Bit
To set the \(n\)-th bit of a
variable x only if condition c (where
c is 0 or 1) is true:
x |= (c << n);How it works:
- If
c == 1,(1 << n)creates a mask with only the \(n\)-th bit set. Performing a bitwise OR sets the \(n\)-th bit inx. - If
c == 0,(0 << n)equals0. Bitwise OR with0leavesxunchanged.
2. Conditionally Clearing a Specific Bit
To clear the \(n\)-th bit of
x only if condition c is true:
x &= ~(c << n);How it works:
- If
c == 1,~(1 << n)creates a mask with all bits set to1except the \(n\)-th bit, which is0. Bitwise AND clears the \(n\)-th bit. - If
c == 0,~(0 << n)creates a mask of all1s (~0). Bitwise AND with all1s leavesxunchanged.
3. Setting a Bit to a Dynamic State (0 or 1)
To unconditionally update the \(n\)-th bit of x to match the
value of v (where v is either 0
or 1), you can use the standard bit-twiddling approach:
x = (x & ~(1 << n)) | (v << n);An alternative formulation using fewer operations uses the XOR trick:
x ^= (-v ^ x) & (1 << n);How it works:
- If
v == 1,-vis all1s.(-1 ^ x)is the bitwise NOT ofx. Masking with(1 << n)extracts the inverted \(n\)-th bit. XORingxwith this value forces the \(n\)-th bit to1. - If
v == 0,-vis all0s.(0 ^ x)isx. Masking with(1 << n)extracts the current \(n\)-th bit. XORingxwith its own bit clears it to0.
4. Conditionally Setting or Clearing Arbitrary Bitmasks
When dealing with arbitrary bit patterns rather than single bits, full-width mask generation applies.
Conditionally
Set Mask M If Condition c Is True:
x |= (M & -c);- If
c == 1,-cis~0, so(M & ~0)evaluates toM.x |= Msets all bits inM. - If
c == 0,-cis0, so(M & 0)evaluates to0.x |= 0leavesxunmodified.
Conditionally
Clear Mask M If Condition c Is True:
x &= ~(M & -c);- If
c == 1,~(M & ~0)evaluates to~M.x &= ~Mclears all bits specified byM. - If
c == 0,~(M & 0)evaluates to~0.x &= ~0leavesxunmodified.
5. Conditionally Merging Bits from Two Sources
To select bits from source A when condition
c == 1 and from source B when condition
c == 0 for a specific mask M:
mask = -c;
x = B ^ ((A ^ B) & mask);This branchless multiplexer (often called a bitwise select) replaces the target bits entirely without needing comparison jumps or branching logic.