编译报错Error: unknown mnemonic 'pcmpestri' -- 'pcmpestri'。
与pcmpestrm指令类似,pcmpestri也是x86 SSE4指令集中的指令。根据指令介绍,其用途是根据指定的比较模式,判断字符串str2的字节是否在str1中出现,返回匹配到的位置索引(首个匹配结果为0的位置)。同样,对于该指令,需要彻底了解其功能,通过C代码重新实现其功能。
指令介绍:
https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE4_2&expand=834
如下代码段是Impala中对pcmpestri指令的调用,该调用参考Intel的_mm_cmpestri接口实现将pcmpestri指令封装成SSE4_cmpestri:
template<int MODE> static inline int SSE4_cmpestri(__m128i str1, int len1, __m128i str2, int len2) { int result; __asm__ __volatile__("pcmpestri %5, %2, %1": "=c"(result) : "x"(str1), "xm"(str2), "a"(len1), "d"(len2), "i"(MODE) : "cc"); return result; }
从指令介绍中看,不同的模式所执行的操作差异较大,完全实现指令功能所需代码行太多。结合代码中对接口的调用,实际使用到的模式为PCMPSTR_EQUAL_EACH | PCMPSTR_UBYTE_OPS | PCMPSTR_NEG_POLARITY。即按照字节长度做匹配,对str1与str2做对应位置字符是否相等判断,若相等,则将对应bit位置置1,最后输出首次出现1的位置。
根据该思路进行代码实现:
#include <arm_neon.h> template <int MODE> static inline int SSE4_cmpestri(int32x4_t str1, int len1, int32x4_t str2, int len2) { __oword a, b; a.m128i = str1; b.m128i = str2; int len_s, len_l; if (len1 > len2) { len_s = len2; len_l = len1; } else { len_s = len1; len_l = len2; } //本例替换的模式STRCMP_MODE = // PCMPSTR_EQUAL_EACH | PCMPSTR_UBYTE_OPS | PCMPSTR_NEG_POLARITY int result; int i; for (i = 0; i < len_s; i++) { if (a.m128i_u8[i] == b.m128i_u8[i]) { break; } } result = i; if (result == len_s) { result = len_l; } return result; }