Skip to content

Commit 0c1e3b8

Browse files
authored
Remove harmful table lookup optimization for bit operations (#5772)
CPUs have efficient instructions for querying, setting and clearing bits, and modern compilers know how to turn simple bit indexing code into such instructions. The table lookup optimizations may have been useful in older versions of rustc, but as of rustc 1.78, they are a net loss. See PR description for more details.
1 parent 30767a6 commit 0c1e3b8

File tree

1 file changed

+6
-18
lines changed

1 file changed

+6
-18
lines changed

arrow-buffer/src/util/bit_util.rs

+6-18
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,6 @@
1717

1818
//! Utils for working with bits
1919
20-
const BIT_MASK: [u8; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
21-
const UNSET_BIT_MASK: [u8; 8] = [
22-
255 - 1,
23-
255 - 2,
24-
255 - 4,
25-
255 - 8,
26-
255 - 16,
27-
255 - 32,
28-
255 - 64,
29-
255 - 128,
30-
];
31-
3220
/// Returns the nearest number that is `>=` than `num` and is a multiple of 64
3321
#[inline]
3422
pub fn round_upto_multiple_of_64(num: usize) -> usize {
@@ -47,7 +35,7 @@ pub fn round_upto_power_of_2(num: usize, factor: usize) -> usize {
4735
/// Returns whether bit at position `i` in `data` is set or not
4836
#[inline]
4937
pub fn get_bit(data: &[u8], i: usize) -> bool {
50-
(data[i >> 3] & BIT_MASK[i & 7]) != 0
38+
data[i / 8] & (1 << (i % 8)) != 0
5139
}
5240

5341
/// Returns whether bit at position `i` in `data` is set or not.
@@ -58,13 +46,13 @@ pub fn get_bit(data: &[u8], i: usize) -> bool {
5846
/// responsible to guarantee that `i` is within bounds.
5947
#[inline]
6048
pub unsafe fn get_bit_raw(data: *const u8, i: usize) -> bool {
61-
(*data.add(i >> 3) & BIT_MASK[i & 7]) != 0
49+
(*data.add(i / 8) & (1 << (i % 8))) != 0
6250
}
6351

6452
/// Sets bit at position `i` for `data` to 1
6553
#[inline]
6654
pub fn set_bit(data: &mut [u8], i: usize) {
67-
data[i >> 3] |= BIT_MASK[i & 7];
55+
data[i / 8] |= 1 << (i % 8);
6856
}
6957

7058
/// Sets bit at position `i` for `data`
@@ -75,13 +63,13 @@ pub fn set_bit(data: &mut [u8], i: usize) {
7563
/// responsible to guarantee that `i` is within bounds.
7664
#[inline]
7765
pub unsafe fn set_bit_raw(data: *mut u8, i: usize) {
78-
*data.add(i >> 3) |= BIT_MASK[i & 7];
66+
*data.add(i / 8) |= 1 << (i % 8);
7967
}
8068

8169
/// Sets bit at position `i` for `data` to 0
8270
#[inline]
8371
pub fn unset_bit(data: &mut [u8], i: usize) {
84-
data[i >> 3] &= UNSET_BIT_MASK[i & 7];
72+
data[i / 8] &= !(1 << (i % 8));
8573
}
8674

8775
/// Sets bit at position `i` for `data` to 0
@@ -92,7 +80,7 @@ pub fn unset_bit(data: &mut [u8], i: usize) {
9280
/// responsible to guarantee that `i` is within bounds.
9381
#[inline]
9482
pub unsafe fn unset_bit_raw(data: *mut u8, i: usize) {
95-
*data.add(i >> 3) &= UNSET_BIT_MASK[i & 7];
83+
*data.add(i / 8) &= !(1 << (i % 8));
9684
}
9785

9886
/// Returns the ceil of `value`/`divisor`

0 commit comments

Comments
 (0)