| 63 | /// Check whether `new` contains any bits not set in `existing`. |
| 64 | #[inline] |
| 65 | pub fn has_new_bits(existing: &[u64], new: &[u64]) -> bool { |
| 66 | assert_eq!(existing.len(), new.len()); |
| 67 | |
| 68 | // This is done in chunks to aid auto-vectorization. |
| 69 | // |
| 70 | // We expect this to (roughly) correspond to a loop with body: |
| 71 | // |
| 72 | // ``` |
| 73 | // vmovdqu ymm0, ymmword ptr [rax + rcx] |
| 74 | // vptest ymm0, ymmword ptr [rsi + rcx] |
| 75 | // lea rcx, [rcx + 32] |
| 76 | // ``` |
| 77 | for (new, existing) in new.chunks_exact(4).zip(existing.chunks_exact(4)) { |
| 78 | let change = (!existing[0] & new[0]) |
| 79 | | (!existing[1] & new[1]) |
| 80 | | (!existing[2] & new[2]) |
| 81 | | (!existing[3] & new[3]); |
| 82 | if change != 0 { |
| 83 | return true; |
| 84 | } |
| 85 | } |
| 86 | false |
| 87 | } |
| 88 | |
| 89 | /// Return the index of any bits within `new` not set in `existing`. |
| 90 | pub fn get_new_bits(existing: &[u64], new: &[u64]) -> Vec<u32> { |