1

运行使用 -xSSE4.1 编译标志构建的可执行文件时出现分段错误。我在支持 SSE4.1、SSE4.2 和 AVX 的机器上运行它。

导致分段错误的内在函数:

m_best_cost_0        = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_tot_cost[0][0]);
m_2nd_best_cost_0    = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_tot_cost[1][0]);

m_best_mv_cost_0     = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_mv_cost[0][0]);
m_2nd_best_mv_cost_0 = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_mv_cost[1][0]);

结构定义:

typedef struct
{
    __declspec(align(16)) WORD16 i2_tot_cost[2][TOT_NUM_PARTS];
    __declspec(align(16)) WORD16 i2_mv_cost[2][TOT_NUM_PARTS];
}mv_refine_ctxt;

TOT_NUM_PARTS 是一个值为 17 的枚举,而 WORD16 是一个短整数。

gdb 中的“layout asm”命令显示了被转换为的内在代码段:

1   ¦0x5cbfec <hme_calc_sad_and_result_num_part_lt_9+108>    mov    0x98(%rdi),%r11                           ¦
2   ¦0x5cbff3 <hme_calc_sad_and_result_num_part_lt_9+115>    mov    0x20(%r12),%r14                           ¦
3   ¦0x5cbff8 <hme_calc_sad_and_result_num_part_lt_9+120>    movslq 0x14(%r12),%rdx                           ¦
4   ¦0x5cbffd <hme_calc_sad_and_result_num_part_lt_9+125>    movslq %eax,%rax                                 ¦
5   ¦0x5cc000 <hme_calc_sad_and_result_num_part_lt_9+128>    movslq %r15d,%r15                                ¦
6   ¦0x5cc003 <hme_calc_sad_and_result_num_part_lt_9+131>    movdqa (%r10),%xmm2                              ¦
7  >¦0x5cc008 <hme_calc_sad_and_result_num_part_lt_9+136>    movdqa 0x22(%r10),%xmm7                          ¦
8   ¦0x5cc00e <hme_calc_sad_and_result_num_part_lt_9+142>    movdqu 0x50(%r10),%xmm11                         ¦
9   ¦0x5cc014 <hme_calc_sad_and_result_num_part_lt_9+148>    movdqu 0x72(%r10),%xmm6 

第 7 行:

0x5cc008 <hme_calc_sad_and_result_num_part_lt_9+136> movdqa 0x22(%r10),%xmm7

给我一个分段错误。

$r10 的值0x7fffd4f22fe0就在执行第 6 行之前;这是一个 16 字节对齐的地址,因此第 6 行执行没有问题。但是第 7 行是从地址加载的,(0x7fffd4f22fe0 + 0x22)该地址不是 16 字节对齐的。gdb 也打印&ps_mv_refine_ctxt->i2_tot_cost[0][0]as 0x7fffd4f22fe0which is $r10 的值。

我担心的是为什么前两个在应该是 movdqu 的时候_mm_loadu_si128翻译成movdqa

当我使用 -xSSE4.2 或 -xAVX 编译标志构建相同的可执行文件时,所有四个 _mm_loadu_si128 指令都被转换为movdqu,因此没有问题。此外,该问题仅在 release-build (-O3 标志)中可见。

我正在使用英特尔 C/C++ 编译器。我觉得__declspec(align(16))结构定义中没有必要。但它不会导致这种奇怪的行为(通过删除它进行测试,发现行为没有变化)。

对不起,很长的帖子。认为这些细节是必要的。

4

0 回答 0