@@ -387,7 +387,7 @@ unsafe fn swap_if_less<T, F>(v_base: *mut T, a_pos: usize, b_pos: usize, is_less
387
387
where
388
388
F: FnMut(&T, &T) -> bool,
389
389
{
390
- // SAFETY: the caller must guarantee that `a ` and `b ` each added to `v_base` yield valid
390
+ // SAFETY: the caller must guarantee that `a_pos ` and `b_pos ` each added to `v_base` yield valid
391
391
// pointers into `v_base`, and are properly aligned, and part of the same allocation.
392
392
unsafe {
393
393
let v_a = v_base.add(a_pos);
@@ -404,16 +404,16 @@ where
404
404
// The equivalent code with a branch would be:
405
405
//
406
406
// if should_swap {
407
- // ptr::swap(left, right , 1);
407
+ // ptr::swap(v_a, v_b , 1);
408
408
// }
409
409
410
410
// The goal is to generate cmov instructions here.
411
- let left_swap = if should_swap { v_b } else { v_a } ;
412
- let right_swap = if should_swap { v_a } else { v_b } ;
411
+ let v_a_swap = should_swap.select_unpredictable( v_b, v_a) ;
412
+ let v_b_swap = should_swap.select_unpredictable( v_a, v_b) ;
413
413
414
- let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap ));
415
- ptr::copy(left_swap , v_a, 1);
416
- ptr::copy_nonoverlapping(&*right_swap_tmp , v_b, 1);
414
+ let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap ));
415
+ ptr::copy(v_a_swap , v_a, 1);
416
+ ptr::copy_nonoverlapping(&*v_b_swap_tmp , v_b, 1);
417
417
}
418
418
}
419
419
@@ -640,26 +640,21 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
640
640
// 1, 1 | c b a d
641
641
let c3 = is_less(&*c, &*a);
642
642
let c4 = is_less(&*d, &*b);
643
- let min = select(c3, c, a);
644
- let max = select(c4, b, d);
645
- let unknown_left = select(c3, a, select(c4, c, b));
646
- let unknown_right = select(c4, d, select(c3, b, c));
643
+ let min = c3.select_unpredictable( c, a);
644
+ let max = c4.select_unpredictable( b, d);
645
+ let unknown_left = c3.select_unpredictable( a, c4.select_unpredictable( c, b));
646
+ let unknown_right = c4.select_unpredictable( d, c3.select_unpredictable( b, c));
647
647
648
648
// Sort the last two unknown elements.
649
649
let c5 = is_less(&*unknown_right, &*unknown_left);
650
- let lo = select(c5, unknown_right, unknown_left);
651
- let hi = select(c5, unknown_left, unknown_right);
650
+ let lo = c5.select_unpredictable( unknown_right, unknown_left);
651
+ let hi = c5.select_unpredictable( unknown_left, unknown_right);
652
652
653
653
ptr::copy_nonoverlapping(min, dst, 1);
654
654
ptr::copy_nonoverlapping(lo, dst.add(1), 1);
655
655
ptr::copy_nonoverlapping(hi, dst.add(2), 1);
656
656
ptr::copy_nonoverlapping(max, dst.add(3), 1);
657
657
}
658
-
659
- #[inline(always)]
660
- fn select<T>(cond: bool, if_true: *const T, if_false: *const T) -> *const T {
661
- if cond { if_true } else { if_false }
662
- }
663
658
}
664
659
665
660
/// SAFETY: The caller MUST guarantee that `v_base` is valid for 8 reads and
0 commit comments