Rollup merge of #93962 - joboet:branchless_slice_ord, r=Mark-Simulacrum
Make [u8]::cmp implementation branchless The current implementation generates rather ugly assembly code, branching when the common parts are equal. By performing the comparison of the lengths upfront using a subtraction, the assembly gets much prettier: https://godbolt.org/z/4e5fnEKGd. This will probably not impact speed too much, as the expensive part is in most cases the `memcmp`, but it sure looks better (I'm porting a sorting algorithm currently, and that branch just bothered me).
This commit is contained in:
commit
9a42121135
1 changed files with 11 additions and 12 deletions
|
@ -1,7 +1,6 @@
|
|||
//! Comparison traits for `[T]`.
|
||||
|
||||
use crate::cmp;
|
||||
use crate::cmp::Ordering::{self, Greater, Less};
|
||||
use crate::cmp::{self, Ordering};
|
||||
use crate::mem;
|
||||
|
||||
use super::from_raw_parts;
|
||||
|
@ -189,18 +188,18 @@ impl<A: Ord> SliceOrd for A {
|
|||
impl SliceOrd for u8 {
|
||||
#[inline]
|
||||
fn compare(left: &[Self], right: &[Self]) -> Ordering {
|
||||
let order =
|
||||
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
|
||||
// We use the minimum of both lengths which guarantees that both regions are
|
||||
// valid for reads in that interval.
|
||||
unsafe { memcmp(left.as_ptr(), right.as_ptr(), cmp::min(left.len(), right.len())) };
|
||||
// Since the length of a slice is always less than or equal to isize::MAX, this never underflows.
|
||||
let diff = left.len() as isize - right.len() as isize;
|
||||
// This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags.
|
||||
let len = if left.len() < right.len() { left.len() } else { right.len() };
|
||||
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
|
||||
// We use the minimum of both lengths which guarantees that both regions are
|
||||
// valid for reads in that interval.
|
||||
let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len) as isize };
|
||||
if order == 0 {
|
||||
left.len().cmp(&right.len())
|
||||
} else if order < 0 {
|
||||
Less
|
||||
} else {
|
||||
Greater
|
||||
order = diff;
|
||||
}
|
||||
order.cmp(&0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue