Title: trouble with result from _mm_cmpestri in c
Tags: c;sse
Question: I'm trying to get the following code to run but the result is always zero. What am I missing?
const int simd_compare_string_mode = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_NEGATIVE_POLARITY | _SIDD_BIT_MASK;
static const unsigned char wtf1[16] = "thisisatesttestt";
static const unsigned char wtf2[16] = "dacb";
const __m128i simd_a = _mm_loadu_si128((__m128i *)&amp;wtf1[0]);
const __m128i simd_b = _mm_loadu_si128((__m128i *)&amp;wtf2[0]);
int result = _mm_cmpestri(simd_b, 4, simd_a , 16, simd_compare_string_mode);
I don't really understand if the result is supposed to be from the 1st input (variable simd_b in this case) or from the second (simd_a). I was thinking in the above example that I might get something (result = 7 or 2?) indicating that the 'a' was in both strings.
Comment: I've never used this particular instruction, but it might be worth studying [the pseudo code for _mm_cmpestri in the intrinsics guide](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpestri&expand=786). It might be a little confusing though as you have your arguments named the opposite way round compared to the documentation.

Comment: Yes, I don't know how or why they decided to jam so much into one instruction - it's almost as if it was designed by committee. ;-) I think I did play with it once to see how all the different modes worked, but after a while I just shook my head and walked away...

Comment: @PaulR: It's probably the most complicated instruction ever.  The instruction set reference manual has a whole 5-page section (4.1) just to document the `imm8` operand that controls the operation modes.  I've looked over it, but I still couldn't made sense of everything you can do with this instruction.  [This blog explains it much better, and show simple functions like strlen or strcmp with it, and `strstr`](https://www.strchr.com/strcmp_and_strlen_using_sse_4.2).  The technical pseudocode is almost too complicated to grok if you don't already know sort of what it's supposed to do.

Comment: Also, on Haswell, `pcmpe*` instructions are about twice as many uops as `pcmpi*`, but latency is about the same.  Throughput running just those instructions is one per 3 cycles vs. one per 4 or 5 cycles.  But if you have explicit-length strings, you probably don't have a choice.

Comment: @Jimbo: You've really chosen to dive in at the deep end, then.  With sharks.  OTOH, usually the best way to learn something new is to have a specific problem you're trying to solve, and this instruction is probably the right tool for the job, esp. if one of the strings is short enough to fit in a single vector.  Otherwise you're going to want to find the unique elements in one string (maybe using `pcmpestr...`, or a counting-sort) before looking in the other string.  Or check the first 16 against the first 16 as an early-out if it's common to have a hit early on, before you uniq the whole str.

Comment: @PaulR Thanks for the link. The pseudo code seems to make a lot of sense and to agree with what I want, which is to know if any of the characters from one string are in the other. This is my first attempt at using intrinsics so I'm worried that I have something else wrong (e.g. alignment, compiler issue/bug, etc.). I'm using TDM-GCC (gcc 5.1?).

Here is the accepted answer: So it turns out the crucial issue was in understanding the roles of the first and second strings and also realizing I was not looking for the index of a match, but rather the number of characters consumed before a match.
My goal is to determine whether or not a string contains certain characters. More specifically, I am trying to skip whitespace when parsing a file and what I'd like to know is how far I need to advance before getting to a non whitespace character.
With this goal in mind, and with the options I've selected (via the 5th input or mode), this is my interpretation of the inputs.
The first input string is the list of characters that you can match. The second input string is your string with unknown contents. The output is how many characters can be consumed before a character in the second string is not in the first string. In the above example the answer is 0, because 't' is not in "dacb."
Here's another code snippet:
//This seems to be our dictionary
static const unsigned char wtf1[16] __attribute__((aligned(16))) = "1234567890123456";
//This seems to be the one that gives the index
static const unsigned char wtf2[16] __attribute__((aligned(16))) = "01d45678901234bc";
const __m128i simd_a = _mm_loadu_si128((__m128i *)&amp;wtf1[0]);
const __m128i simd_b = _mm_loadu_si128((__m128i *)&amp;wtf2[0]);
int result = _mm_cmpestri(simd_a, 16, simd_b , 4, simd_compare_string_mode);
In this example our result is 2, because the first two characters in our second input ("01") are in the first string. The 'd' is not. This function allows specifying the lengths of the strings. If I make the strings the same, the result is 4, since my second input is "limited" to 4 characters (4th input in the above function). It will be interesting to see how this compares (in terms of speed) to _mm_cmpistri (notice the 'i' instead of the 'e') which does not take in string length parameters.


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 6, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2016:00:05/17/16', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<c><sse>', 'Title': 'trouble with result from _mm_cmpestri in c', 'ViewCount': 821, 'id': 37266851, 'user_AboutMe': '', 'user_AccountId': 399188.0, 'user_DisplayName': 'Jimbo', 'user_Reputation': 2379.0, 'user_Views': 260.0, 'user_id': 764365.0}}