Skip to content

Commit 2f78bce

Browse files
committed
unroll slice::equal impl
1 parent 2624523 commit 2f78bce

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

library/core/src/slice/cmp.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,56 @@ impl<A, B> SlicePartialEq<B> for [A]
5555
where
5656
A: PartialEq<B>,
5757
{
58+
#[inline]
5859
default fn equal(&self, other: &[B]) -> bool {
5960
if self.len() != other.len() {
6061
return false;
6162
}
6263

63-
self.iter().zip(other.iter()).all(|(x, y)| x == y)
64+
// at least 8 items for unrolling to make sense (4 peeled + 4+ unrolled)
65+
if self.len() < 8 {
66+
return eq_small(self, other);
67+
}
68+
69+
eq_unroll(self, other)
6470
}
6571
}
6672

73+
#[inline]
74+
fn eq_small<A, B>(a: &[A], b: &[B]) -> bool
75+
where
76+
A: PartialEq<B>,
77+
{
78+
a.iter().zip(b).all(|(a, b)| a == b)
79+
}
80+
81+
fn eq_unroll<A, B>(a: &[A], b: &[B]) -> bool
82+
where
83+
A: PartialEq<B>,
84+
{
85+
let (mut chunks_a, residual_a) = a.as_chunks::<4>();
86+
let (mut chunks_b, residual_b) = b.as_chunks::<4>();
87+
let peeled_a = chunks_a.take_first().unwrap();
88+
let peeled_b = chunks_b.take_first().unwrap();
89+
90+
// peel the first chunk and do a short-circuiting comparison to bail early on mismatches
91+
// in case comparisons are expensive
92+
let mut result = eq_small(peeled_a, peeled_b);
93+
94+
// then check the residual, another chance to bail early
95+
result = result && eq_small(residual_a, residual_b);
96+
97+
// iter.all short-circuits which means the backend can't unroll the loop due to early exits.
98+
// So we unroll it manually.
99+
result = result
100+
&& chunks_a
101+
.iter()
102+
.zip(chunks_b)
103+
.all(|(a, b)| (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]));
104+
105+
result
106+
}
107+
67108
// When each element can be compared byte-wise, we can compare all the bytes
68109
// from the whole size in one call to the intrinsics.
69110
impl<A, B> SlicePartialEq<B> for [A]

0 commit comments

Comments
 (0)