我正在努力将MSVC应用程序迁移到Red-Hat Linux,并且遇到了一些使用的内在问题。我正在使用GCC 4.8.3以及以下命令行。
gcc -c file.c -o file.o -O2 -g -masm=intel -m32 -mavx -mavx2 -D_MMX_ -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -pthread -fno-omit-frame-pointer -fno-tree-pre -fno-builtin-printf -Werror
伪代码是这样的
#include <immintrin.h> // AVX/AVX2
void func_with_intrins(int x, int y, int h)
{
short ddx;
short ddy;
int yh;
ddx = xpos & 7;
ddy = ypos & 7;
...
for (yh = 0; yh < (h>>2); yh++)
{
if ((ddx + ddy) != 0)
{
__m128i ddxw = _mm_set1_epi16(ddx);
...
}
...
}
}
我已经读过_mm_set1_epi16内在函数可以扩展为vpbroadcastw,我已经通过查看生成的汇编文件确认了这一点。
vpbroadcastw xmm0, XMMWORD PTR [ebp-216]
来自here
的定义VPBROADCASTW xmm1, xmm2/m16
VPBROADCASTB/W/D/Q is supported in both 128-bit and 256-bit wide versions.
GCC给我的错误是
Error: operand size mismatch for `vpbroadcastw'
当我将优化级别从O2
更改为O0
时,程序集会有很大不同,并且不会使用vpbroadcastw
指令。
由于我使用内在函数,我不知道该怎么做。将文件编译为O0不是一个选项。如果我将__m128i ddxw
声明移到看似编译的循环之外,但我想我会更改底层功能。当移动到for循环之前时,vpbroadcastw
代码需要两个xmm
寄存器(堆栈变量是vmovdqa'd到xmm寄存器中)所以我认为gcc用完寄存器因此试图调用vpbroadcastw
,第二个操作数是堆栈偏移量。