Skip to content

Commit d585eec

Browse files
committed
Refactor binary_search_by to use conditional moves
Refactor the if/else checking on cmp::Ordering variants to a "branchless" reassignment of left and right. This change results in fewer branches and instructions.
1 parent 341efb1 commit d585eec

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

library/core/src/slice/mod.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
#![stable(feature = "rust1", since = "1.0.0")]
88

9-
use crate::cmp::Ordering::{self, Greater, Less};
9+
use crate::cmp::Ordering::{self, Equal, Greater, Less};
1010
use crate::fmt;
1111
use crate::intrinsics::{assert_unsafe_precondition, exact_div};
1212
use crate::marker::Copy;
@@ -2844,14 +2844,13 @@ impl<T> [T] {
28442844
// we have `left + size/2 < self.len()`, and this is in-bounds.
28452845
let cmp = f(unsafe { self.get_unchecked(mid) });
28462846

2847-
// The reason why we use if/else control flow rather than match
2848-
// is because match reorders comparison operations, which is perf sensitive.
2849-
// This is x86 asm for u8: https://rust.godbolt.org/z/8Y8Pra.
2850-
if cmp == Less {
2851-
left = mid + 1;
2852-
} else if cmp == Greater {
2853-
right = mid;
2854-
} else {
2847+
// This control flow produces conditional moves, which results in
2848+
// fewer branches and instructions than if/else or matching on
2849+
// cmp::Ordering.
2850+
// This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx.
2851+
left = if cmp == Less { mid + 1 } else { left };
2852+
right = if cmp == Greater { mid } else { right };
2853+
if cmp == Equal {
28552854
// SAFETY: same as the `get_unchecked` above
28562855
unsafe { crate::intrinsics::assume(mid < self.len()) };
28572856
return Ok(mid);

0 commit comments

Comments
 (0)