Skip to content

Commit 3960ce6

Browse files
committed
Make [u8]::cmp implementation branchless
1 parent 9a60099 commit 3960ce6

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

Diff for: library/core/src/slice/cmp.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Comparison traits for `[T]`.
22
3-
use crate::cmp;
4-
use crate::cmp::Ordering::{self, Greater, Less};
3+
use crate::cmp::{self, Ordering};
54
use crate::mem;
65

76
use super::from_raw_parts;
@@ -189,18 +188,18 @@ impl<A: Ord> SliceOrd for A {
189188
impl SliceOrd for u8 {
190189
#[inline]
191190
fn compare(left: &[Self], right: &[Self]) -> Ordering {
192-
let order =
193-
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
194-
// We use the minimum of both lengths which guarantees that both regions are
195-
// valid for reads in that interval.
196-
unsafe { memcmp(left.as_ptr(), right.as_ptr(), cmp::min(left.len(), right.len())) };
191+
// Since the length of a slice is always less than or equal to isize::MAX, this never underflows.
192+
let diff = left.len() as isize - right.len() as isize;
193+
// This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags.
194+
let len = if left.len() < right.len() { left.len() } else { right.len() };
195+
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
196+
// We use the minimum of both lengths which guarantees that both regions are
197+
// valid for reads in that interval.
198+
let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len) as isize };
197199
if order == 0 {
198-
left.len().cmp(&right.len())
199-
} else if order < 0 {
200-
Less
201-
} else {
202-
Greater
200+
order = diff;
203201
}
202+
order.cmp(&0)
204203
}
205204
}
206205

0 commit comments

Comments
 (0)