Compares packed strings with implicit lengths in a and b using the
control in IMM8 and return the generated index. Similar to
_mm_cmpestri with the exception that _mm_cmpestri requires the
lengths of a and b to be explicitly specified.
Control modes
The control specified by IMM8 may be one or more of the following.
Data size and signedness
Comparison options
Result polarity
Bit returned
Examples
Finds a substring using _SIDD_CMP_EQUAL_ORDERED
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
# fn main() {
# if is_x86_feature_detected!("sse4.2") {
# #[target_feature(enable = "sse4.2")]
# unsafe fn worker() {
let haystack = b"This is a long string of text data\r\n\tthat extends
multiple lines";
let needle = b"\r\n\t\0\0\0\0\0\0\0\0\0\0\0\0\0";
let a = unsafe { _mm_loadu_si128(needle.as_ptr() as *const _) };
let hop = 16;
let mut indexes = Vec::new();
for (i, chunk) in haystack.chunks(hop).enumerate() {
let b = unsafe { _mm_loadu_si128(chunk.as_ptr() as *const _) };
let idx = _mm_cmpistri(a, b, _SIDD_CMP_EQUAL_ORDERED);
if idx != 16 {
indexes.push((idx as usize) + (i * hop));
}
}
assert_eq!(indexes, vec![34]);
# }
# unsafe { worker(); }
# }
# }
The _mm_cmpistri intrinsic may also be used to find the existence of
one or more of a given set of characters in the haystack.
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
# fn main() {
# if is_x86_feature_detected!("sse4.2") {
# #[target_feature(enable = "sse4.2")]
# unsafe fn worker() {
let password = b"hunter2\0\0\0\0\0\0\0\0\0";
let special_chars = b"!@#$%^&*()[]:;<>";
let a = unsafe { _mm_loadu_si128(special_chars.as_ptr() as *const _) };
let b = unsafe { _mm_loadu_si128(password.as_ptr() as *const _) };
let idx = _mm_cmpistri(a.into(), b.into(), _SIDD_CMP_EQUAL_ANY);
if idx < 16 {
println!("Congrats! Your password contains a special character");
# panic!("{:?} does not contain a special character", password);
} else {
println!("Your password should contain a special character");
}
# }
# unsafe { worker(); }
# }
# }
Finds the index of the first character in the haystack that is within a
range of characters.
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
# fn main() {
# if is_x86_feature_detected!("sse4.2") {
# #[target_feature(enable = "sse4.2")]
# unsafe fn worker() {
# let b = b":;<=>?@[\\]^_`abc";
# let b = unsafe { _mm_loadu_si128(b.as_ptr() as *const _) };
let a = b"AZaz09\0\0\0\0\0\0\0\0\0\0";
let a = unsafe { _mm_loadu_si128(a.as_ptr() as *const _) };
let idx = _mm_cmpistri(a, b, _SIDD_CMP_RANGES);
if idx < 16 {
println!("Found an alpha numeric character");
# assert_eq!(idx, 13);
} else {
println!("Did not find an alpha numeric character");
}
# }
# unsafe { worker(); }
# }
# }
Working with 16-bit characters.
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
# fn main() {
# if is_x86_feature_detected!("sse4.2") {
# #[target_feature(enable = "sse4.2")]
# unsafe fn worker() {
# let mut some_utf16_words = [0u16; 8];
# let mut more_utf16_words = [0u16; 8];
# '❤'.encode_utf16(&mut some_utf16_words);
# '𝕊'.encode_utf16(&mut more_utf16_words);
let a = unsafe { _mm_loadu_si128(some_utf16_words.as_ptr() as *const _) };
let b = unsafe { _mm_loadu_si128(more_utf16_words.as_ptr() as *const _) };
let idx = _mm_cmpistri(a, b, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH);
if idx == 0 {
println!("16-bit unicode strings were equal!");
# panic!("Strings should not be equal!")
} else {
println!("16-bit unicode strings were not equal!");
}
# }
# unsafe { worker(); }
# }
# }
Intel's documentation