Skip to content

Commit fbd7485

Browse files
Improve codegen for mixing in length (#112)
1 parent e745544 commit fbd7485

2 files changed

Lines changed: 35 additions & 10 deletions

File tree

src/aes_hash.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,6 @@ impl AHasher {
8282
}
8383
}
8484

85-
#[inline(always)]
86-
fn add_in_length(&mut self, length: u64) {
87-
//This will be scrambled by the next AES round.
88-
let mut enc: [u64; 2] = self.enc.convert();
89-
enc[0] = enc[0].wrapping_add(length);
90-
self.enc = enc.convert();
91-
}
92-
9385
#[inline(always)]
9486
fn hash_in(&mut self, new_value: u128) {
9587
self.enc = aesenc(self.enc, new_value);
@@ -159,7 +151,8 @@ impl Hasher for AHasher {
159151
fn write(&mut self, input: &[u8]) {
160152
let mut data = input;
161153
let length = data.len();
162-
self.add_in_length(length as u64);
154+
add_in_length(&mut self.enc, length as u64);
155+
163156
//A 'binary search' on sizes reduces the number of comparisons.
164157
if data.len() <= 8 {
165158
let value = read_small(data);
@@ -337,7 +330,8 @@ impl Hasher for AHasherStr {
337330
self.0.enc = aesdec(self.0.sum, self.0.enc);
338331
self.0.enc = aesenc(aesenc(self.0.enc, self.0.key), self.0.enc);
339332
} else {
340-
self.0.add_in_length(bytes.len() as u64);
333+
add_in_length(&mut self.0.enc, bytes.len() as u64);
334+
341335
let value = read_small(bytes).convert();
342336
self.0.sum = shuffle_and_add(self.0.sum, value);
343337
self.0.enc = aesdec(self.0.sum, self.0.enc);

src/operations.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,29 @@ pub(crate) fn aesdec(value: u128, xor: u128) -> u128 {
146146
}
147147
}
148148

149+
#[inline(always)]
150+
pub(crate) fn add_in_length(enc: &mut u128, len: u64) {
151+
#[cfg(all(target_arch = "x86_64", target_feature = "sse2", not(miri)))]
152+
{
153+
#[cfg(target_arch = "x86_64")]
154+
use core::arch::x86_64::*;
155+
156+
unsafe {
157+
let enc = enc as *mut u128;
158+
let len = _mm_cvtsi64_si128(len as i64);
159+
let data = _mm_loadu_si128(enc.cast());
160+
let sum = _mm_add_epi64(data, len);
161+
_mm_storeu_si128(enc.cast(), sum);
162+
}
163+
}
164+
#[cfg(not(all(target_arch = "x86_64", target_feature = "sse2", not(miri))))]
165+
{
166+
let mut t: [u64; 2] = enc.convert();
167+
t[0] = t[0].wrapping_add(len);
168+
*enc = t.convert();
169+
}
170+
}
171+
149172
#[cfg(test)]
150173
mod test {
151174
use super::*;
@@ -327,4 +350,12 @@ mod test {
327350
shuffled = shuffle(shuffled);
328351
}
329352
}
353+
354+
#[test]
355+
fn test_add_length() {
356+
let mut enc = (u64::MAX as u128) << 64 | 50;
357+
add_in_length(&mut enc, u64::MAX);
358+
assert_eq!(enc >> 64, u64::MAX as u128);
359+
assert_eq!(enc as u64, 49);
360+
}
330361
}

0 commit comments

Comments
 (0)