Skip to content

Commit 2fa330e

Browse files
committed
Convert cfg blocks to cfg_if
1 parent f46fcfe commit 2fa330e

File tree

4 files changed

+68
-79
lines changed

4 files changed

+68
-79
lines changed

core/src/slice/sort/select.rs

+12-16
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,12 @@ where
4242
let min_idx = min_index(v, &mut is_less).unwrap();
4343
v.swap(min_idx, index);
4444
} else {
45-
#[cfg(not(feature = "optimize_for_size"))]
46-
{
47-
partition_at_index_loop(v, index, None, &mut is_less);
48-
}
49-
50-
#[cfg(feature = "optimize_for_size")]
51-
{
52-
median_of_medians(v, &mut is_less, index);
45+
cfg_if! {
46+
if #[cfg(feature = "optimize_for_size")] {
47+
median_of_medians(v, &mut is_less, index);
48+
} else {
49+
partition_at_index_loop(v, index, None, &mut is_less);
50+
}
5351
}
5452
}
5553

@@ -178,14 +176,12 @@ fn median_of_medians<T, F: FnMut(&T, &T) -> bool>(mut v: &mut [T], is_less: &mut
178176
loop {
179177
if v.len() <= INSERTION_SORT_THRESHOLD {
180178
if v.len() >= 2 {
181-
#[cfg(not(feature = "optimize_for_size"))]
182-
{
183-
insertion_sort_shift_left(v, 1, is_less);
184-
}
185-
186-
#[cfg(feature = "optimize_for_size")]
187-
{
188-
bubble_sort(v, is_less);
179+
cfg_if! {
180+
if #[cfg(feature = "optimize_for_size")] {
181+
bubble_sort(v, is_less);
182+
} else {
183+
insertion_sort_shift_left(v, 1, is_less);
184+
}
189185
}
190186
}
191187

core/src/slice/sort/stable/mod.rs

+31-33
Original file line numberDiff line numberDiff line change
@@ -39,40 +39,38 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
3939
return;
4040
}
4141

42-
#[cfg(not(feature = "optimize_for_size"))]
43-
{
44-
// More advanced sorting methods than insertion sort are faster if called in
45-
// a hot loop for small inputs, but for general-purpose code the small
46-
// binary size of insertion sort is more important. The instruction cache in
47-
// modern processors is very valuable, and for a single sort call in general
48-
// purpose code any gains from an advanced method are cancelled by i-cache
49-
// misses during the sort, and thrashing the i-cache for surrounding code.
50-
const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20;
51-
if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) {
52-
insertion_sort_shift_left(v, 1, is_less);
53-
return;
54-
}
55-
56-
driftsort_main::<T, F, BufT>(v, is_less);
57-
}
58-
59-
#[cfg(feature = "optimize_for_size")]
60-
{
61-
let alloc_len = len / 2;
62-
63-
// For small inputs 4KiB of stack storage suffices, which allows us to avoid
64-
// calling the (de-)allocator. Benchmarks showed this was quite beneficial.
65-
let mut stack_buf = AlignedStorage::<T, 4096>::new();
66-
let stack_scratch = stack_buf.as_uninit_slice_mut();
67-
let mut heap_buf;
68-
let scratch = if stack_scratch.len() >= alloc_len {
69-
stack_scratch
42+
cfg_if! {
43+
if #[cfg(feature = "optimize_for_size")] {
44+
let alloc_len = len / 2;
45+
46+
// For small inputs 4KiB of stack storage suffices, which allows us to avoid
47+
// calling the (de-)allocator. Benchmarks showed this was quite beneficial.
48+
let mut stack_buf = AlignedStorage::<T, 4096>::new();
49+
let stack_scratch = stack_buf.as_uninit_slice_mut();
50+
let mut heap_buf;
51+
let scratch = if stack_scratch.len() >= alloc_len {
52+
stack_scratch
53+
} else {
54+
heap_buf = BufT::with_capacity(alloc_len);
55+
heap_buf.as_uninit_slice_mut()
56+
};
57+
58+
tiny::mergesort(v, scratch, is_less);
7059
} else {
71-
heap_buf = BufT::with_capacity(alloc_len);
72-
heap_buf.as_uninit_slice_mut()
73-
};
74-
75-
tiny::mergesort(v, scratch, is_less);
60+
// More advanced sorting methods than insertion sort are faster if called in
61+
// a hot loop for small inputs, but for general-purpose code the small
62+
// binary size of insertion sort is more important. The instruction cache in
63+
// modern processors is very valuable, and for a single sort call in general
64+
// purpose code any gains from an advanced method are cancelled by i-cache
65+
// misses during the sort, and thrashing the i-cache for surrounding code.
66+
const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20;
67+
if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) {
68+
insertion_sort_shift_left(v, 1, is_less);
69+
return;
70+
}
71+
72+
driftsort_main::<T, F, BufT>(v, is_less);
73+
}
7674
}
7775
}
7876

core/src/slice/sort/unstable/mod.rs

+19-21
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,26 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) {
3030
return;
3131
}
3232

33-
#[cfg(not(feature = "optimize_for_size"))]
34-
{
35-
// More advanced sorting methods than insertion sort are faster if called in
36-
// a hot loop for small inputs, but for general-purpose code the small
37-
// binary size of insertion sort is more important. The instruction cache in
38-
// modern processors is very valuable, and for a single sort call in general
39-
// purpose code any gains from an advanced method are cancelled by i-cache
40-
// misses during the sort, and thrashing the i-cache for surrounding code.
41-
const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20;
42-
if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) {
43-
insertion_sort_shift_left(v, 1, is_less);
44-
return;
45-
}
46-
47-
ipnsort(v, is_less);
48-
}
33+
cfg_if! {
34+
if #[cfg(feature = "optimize_for_size")] {
35+
// SAFETY: We checked that `len >= 2`.
36+
unsafe {
37+
heapsort::heapsort(v, is_less);
38+
}
39+
} else {
40+
// More advanced sorting methods than insertion sort are faster if called in
41+
// a hot loop for small inputs, but for general-purpose code the small
42+
// binary size of insertion sort is more important. The instruction cache in
43+
// modern processors is very valuable, and for a single sort call in general
44+
// purpose code any gains from an advanced method are cancelled by i-cache
45+
// misses during the sort, and thrashing the i-cache for surrounding code.
46+
const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20;
47+
if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) {
48+
insertion_sort_shift_left(v, 1, is_less);
49+
return;
50+
}
4951

50-
#[cfg(feature = "optimize_for_size")]
51-
{
52-
// SAFETY: We checked that `len >= 2`.
53-
unsafe {
54-
heapsort::heapsort(v, is_less);
52+
ipnsort(v, is_less);
5553
}
5654
}
5755
}

core/src/slice/sort/unstable/quicksort.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,12 @@ const fn inst_partition<T, F: FnMut(&T, &T) -> bool>() -> fn(&mut [T], &T, &mut
141141
if mem::size_of::<T>() <= MAX_BRANCHLESS_PARTITION_SIZE {
142142
// Specialize for types that are relatively cheap to copy, where branchless optimizations
143143
// have large leverage e.g. `u64` and `String`.
144-
145-
#[cfg(not(feature = "optimize_for_size"))]
146-
{
147-
partition_lomuto_branchless_cyclic::<T, F>
148-
}
149-
150-
#[cfg(feature = "optimize_for_size")]
151-
{
152-
partition_lomuto_branchless_simple::<T, F>
144+
cfg_if! {
145+
if #[cfg(feature = "optimize_for_size")] {
146+
partition_lomuto_branchless_simple::<T, F>
147+
} else {
148+
partition_lomuto_branchless_cyclic::<T, F>
149+
}
153150
}
154151
} else {
155152
partition_hoare_branchy_cyclic::<T, F>

0 commit comments

Comments
 (0)