Visual studio 这是VC&x2B中的一个bug吗+;优化器还是在我的代码中?
使用VS2012 Update 1生成的控制台项目尝试了以下向量减法代码。 除了禁用全局优化和启用汇编程序列表之外,我没有真正接触默认选项 在Windows 7 x64 SP1上使用x64版本配置编译Visual studio 这是VC&x2B中的一个bug吗+;优化器还是在我的代码中?,visual-studio,visual-c++,visual-studio-2012,visual-c++-2012,Visual Studio,Visual C++,Visual Studio 2012,Visual C++ 2012,使用VS2012 Update 1生成的控制台项目尝试了以下向量减法代码。 除了禁用全局优化和启用汇编程序列表之外,我没有真正接触默认选项 在Windows 7 x64 SP1上使用x64版本配置编译 #include <stdio.h> #include <tchar.h> #include <emmintrin.h> typedef unsigned short ushort; typedef unsigned int uint; void prin
#include <stdio.h>
#include <tchar.h>
#include <emmintrin.h>
typedef unsigned short ushort;
typedef unsigned int uint;
void print(__m128i i)
{
auto& arr = i.m128i_u16;
printf("[%d %d %d %d %d %d %d %d]\n", arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]);
}
int _tmain(int argc, _TCHAR* argv[])
{
const int lineSize = 912;
ushort input[lineSize];
ushort vals[lineSize];
// printf("%X %X\n", input, vals); // note this one
for (uint i=0; i<lineSize; i+=8)
{
__m128i vecinput = _mm_loadu_si128((__m128i*) &input[i]);
__m128i vecvals = _mm_loadu_si128((__m128i*) &vals[i]);
__m128i output = _mm_subs_epu16(vecinput, vecvals);
print(output);
printf("===\n");
}
return 0;
}
#包括
#包括
#包括
typedef无符号短ushort;
typedef无符号整数单元;
作废打印(m128i)
{
自动&arr=i.m128i_16;
printf(“[%d%d%d%d%d%d%d%d%d]\n”,arr[0],arr[1],arr[2],arr[3],arr[4],arr[5],arr[6],arr[7]);
}
int _tmain(int argc,_TCHAR*argv[]
{
常量int lineSize=912;
ushort输入[lineSize];
ushort VAL[线路尺寸];
//printf(“%X%X\n”,输入,VAL);//注意这个
对于(uint i=0;i您从未初始化数组ushort input[lineSize]
和ushort vals[lineSize]
,因此优化器碰巧将它们视为相同的,这对于未定义的行为是很好的
当您有printf(“%X%X\n”,输入,VAL)时
在那里调用,您将数组的地址传递给一个外部函数,因此优化器有理由相信它们指向的内存可能会被该外部函数更新。您有几个printf
s,但我猜您指的是print
中的一个。是的,如果您不使用值,它们将被删除。因此这是错误的,您实际期望的是什么?print/printf的用法与预期一致。代码中使用了VAL。但VC错误地将其视为输入。在我的机器上,使用v110和v110_xp工具集进行测试时,完全没有重新编写。很难猜测是什么原因导致我的机器和您的机器之间存在如此大的差异,但您没有记录发布完全建立编译选项。至少发布C/C++命令行的内容。并在编译器文件上记录时间戳。然后在另一台机器上尝试。@Hans:repos withcl/FAcs/Ox/test.cpp
usingMicrosoft(R)C/C++优化编译器版本17.00.50727.1 for x64
。好的,我不知道优化器这样做是合法的。故意不初始化数组以快速获得“随机”值(不,我在实际代码中没有这样做)。你知道优化器为什么这样做吗?我的意思是,通常这样的代码应该指示一个错误,而不是一个优化机会。优化器不担心警告或错误;它只是查看内存的实际使用情况,并相应地注册和优化。编译器的其他部分将负责生成诊断号关于使用未初始化的变量,这可能会被您获取数组元素的地址并将地址传递给\u mm\u loadu\u si128()
内部变量所愚弄。我仍然没有使用/Ox重新编程,但注意到它加载的是输入而不是VAL。初始化数组确实解决了这一问题。
; 20 : const int lineSize = 912;
; 21 : ushort input[lineSize];
; 22 : ushort vals[lineSize];
; without printf
; 23 : // printf("%X %X\n", input, vals);
; with printf
; 23 : printf("%X %X\n", input, vals);
lea r8, QWORD PTR vals$[rsp]
lea rdx, QWORD PTR input$[rsp]
lea rcx, OFFSET FLAT:??_C@_06NBKGFLKK@?$CFX?5?$CFX?6?$AA@
call QWORD PTR __imp_printf
; 24 :
; 25 : for (uint i=0; i<lineSize; i+=8)
xor esi, esi
lea ebp, QWORD PTR [rsi+114]
npad 2
$LL3@wmain:
; 26 : {
; 27 : __m128i vecinput = _mm_loadu_si128((__m128i*) &input[i]);
movdqu xmm1, XMMWORD PTR input$[rsp+rsi]
; 28 : __m128i vecvals = _mm_loadu_si128((__m128i*) &vals[i]);
; without printf
movdqu xmm0, xmm1
; with printf
movdqu xmm0, XMMWORD PTR vals$[rsp+rsi]
; 29 :
; 30 : __m128i output = _mm_subs_epu16(vecinput, vecvals);
; without printf
psubusw xmm1, xmm1
; with printf
psubusw xmm1, xmm0
; 15 : printf("[%d %d %d %d %d %d %d %d]\n", arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]);
pextrw ax, xmm1, 7
movzx edi, ax
pextrw ax, xmm1, 6
movzx ebx, ax
pextrw ax, xmm1, 5
mov DWORD PTR [rsp+64], edi
movzx r11d, ax
pextrw ax, xmm1, 4
mov DWORD PTR [rsp+56], ebx
movzx r10d, ax
pextrw ax, xmm1, 3
mov DWORD PTR [rsp+48], r11d
movzx ecx, ax
pextrw ax, xmm1, 2
mov DWORD PTR [rsp+40], r10d
movzx r9d, ax
pextrw ax, xmm1, 1
mov DWORD PTR [rsp+32], ecx
movzx r8d, ax
lea rcx, OFFSET FLAT:??_C@_0BL@ONEMJFJK@?$FL?$CFd?7?$CFd?7?$CFd?7?$CFd?7?$CFd?7?$CFd?7?$CFd?7?$CFd?$FN?6?$AA@
movd eax, xmm1
movzx edx, ax
call QWORD PTR __imp_printf
; 31 : print(output);
; 32 : printf("===\n");
lea rcx, OFFSET FLAT:??_C@_04LEHBMKOA@?$DN?$DN?$DN?6?$AA@
call QWORD PTR __imp_printf
lea rsi, QWORD PTR [rsi+16]
dec rbp
jne $LL3@wmain
; 33 : }
; 34 :
; 35 : return 0;
xor eax, eax
; 95 : }
mov rcx, QWORD PTR __$ArrayPad$[rsp]
xor rcx, rsp
call __security_check_cookie
lea r11, QWORD PTR [rsp+1920]
mov rbx, QWORD PTR [r11+16]
mov rbp, QWORD PTR [r11+24]
mov rsi, QWORD PTR [r11+32]
mov rsp, r11
pop rdi
ret 0
wmain ENDP