@@ -60,10 +60,50 @@ where
60
60
return false ;
61
61
}
62
62
63
- self . iter ( ) . zip ( other. iter ( ) ) . all ( |( x, y) | x == y)
63
+ // at least 8 items for unrolling to make sense (4 peeled + 4+ unrolled)
64
+ if self . len ( ) < 8 {
65
+ return eq_small ( self , other) ;
66
+ }
67
+
68
+ eq_unroll ( self , other)
64
69
}
65
70
}
66
71
72
+ #[ inline]
73
+ fn eq_small < A , B > ( a : & [ A ] , b : & [ B ] ) -> bool
74
+ where
75
+ A : PartialEq < B > ,
76
+ {
77
+ a. iter ( ) . zip ( b) . all ( |( a, b) | a == b)
78
+ }
79
+
80
+ fn eq_unroll < A , B > ( a : & [ A ] , b : & [ B ] ) -> bool
81
+ where
82
+ A : PartialEq < B > ,
83
+ {
84
+ let ( mut chunks_a, residual_a) = a. as_chunks :: < 4 > ( ) ;
85
+ let ( mut chunks_b, residual_b) = b. as_chunks :: < 4 > ( ) ;
86
+ let peeled_a = chunks_a. take_first ( ) . unwrap ( ) ;
87
+ let peeled_b = chunks_b. take_first ( ) . unwrap ( ) ;
88
+
89
+ // peel the first chunk and do a short-circuiting comparison to bail early on mismatches
90
+ // in case comparisons are expensive
91
+ let mut result = eq_small ( peeled_a, peeled_b) ;
92
+
93
+ // then check the residual, another chance to bail early
94
+ result = result && eq_small ( residual_a, residual_b) ;
95
+
96
+ // iter.all short-circuits which means the backend can't unroll the loop due to early exits.
97
+ // So we unroll it manually.
98
+ result = result
99
+ && chunks_a
100
+ . iter ( )
101
+ . zip ( chunks_b)
102
+ . all ( |( a, b) | ( a[ 0 ] == b[ 0 ] ) & ( a[ 1 ] == b[ 1 ] ) & ( a[ 2 ] == b[ 2 ] ) & ( a[ 3 ] == b[ 3 ] ) ) ;
103
+
104
+ result
105
+ }
106
+
67
107
// When each element can be compared byte-wise, we can compare all the bytes
68
108
// from the whole size in one call to the intrinsics.
69
109
impl < A , B > SlicePartialEq < B > for [ A ]
0 commit comments