中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

替换x86 pcmpestrm汇编指令

现象描述

编译报错Error: unknown mnemonic 'pcmpestrm' -- 'pcmpestrm'。

问题原因

pcmpestrm指令是x86指令集中SSE4中的指令。根据指令介绍,其用途是根据指定的比较模式,判断字符串str2的字节是否在str1中出现,将每个字节的对比结果返回(最大长度16字节)。该指令是典型的x86复杂指令,通过一条指令即完成复杂的字符串匹配功能,鲲鹏架构中无类似实现。对于这种指令,需要彻底了解其功能,通过C代码重新实现其功能。

指令介绍:

https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE4_2&expand=835

https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/bb514080(v=vs.100)

处理步骤

如下代码段是Impala中对pcmpestrm指令的调用,该调用参考Intel的_mm_cmpestrm接口实现将pcmpestrm指令封装成SSE4_cmpestrm:

template<int MODE> 
static inline __m128i SSE4_cmpestrm(__m128i str1, int len1, __m128i str2, int len2) { 
#ifdef __clang__ 
  /// Use asm reg rather than Yz output constraint to workaround LLVM bug 13199 - 
  /// clang doesn't support Y-prefixed asm constraints. 
  register volatile __m128i result asm ("xmm0"); 
  __asm__ __volatile__ ("pcmpestrm %5, %2, %1": "=x"(result) : "x"(str1), "xm"(str2), "a"(len1), "d"(len2), "i"(MODE) : "cc"); 
#else 
  __m128i result; 
  __asm__ __volatile__ ("pcmpestrm %5, %2, %1": "=Yz"(result) : "x"(str1), "xm"(str2), "a"(len1), "d"(len2), "i"(MODE) : "cc"); 
#endif 
  return result; 
}

从指令介绍中看,不同的模式所执行的操作差异较大,完全实现指令功能所需代码行太多。结合代码中对接口的调用,实际使用到的模式为PCMPSTR_EQUAL_ANY |PCMPSTR_UBYTE_OPS。即按照字节长度做匹配,对比str2中的每个字符是否在str1中出现,若出现,则将对应bit位置置1。

根据识别到的功能进行代码实现:

#include <arm_neon.h>
typedefunion __attribute__((aligned(16))) __oword {
int32x4_t m128i;
uint8_tm128i_u8[16];
} __oword;
template <intMODE>
staticinlineuint16_tSSE4_cmpestrm(int32x4_tstr1, intlen1, int32x4_tstr2, intlen2){
    __oword a, b;
    a.m128i = str1;
    b.m128i = str2;
    uint16_t result = 0;
    uint16_t i = 0;
    uint16_t j = 0;
    // Impala中用到的模式 STRCHR_MODE = PCMPSTR_EQUAL_ANY | PCMPSTR_UBYTE_OPS
    for (i = 0; i < len2; i++)
    {
        for (j = 0; j < len1; j++)
        {
            if (a.m128i_u8[j] == b.m128i_u8[i])
            {
                result |= (1 << i);
            }
        }
    }
    return result;
}

无直接替代指令的场景,需要结合指令功能、所需功能共同分析,切忌生搬硬套直接代码复制替换。