为Win32编译的Win64 SSE代码产生不正确的性能计数器结果

时间:2015-10-09 14:41:43

标签: winapi sse icc

我有一个正常运行的SSE代码,我通常为Win64编译(我使用的是英特尔C ++编译器14)。完成后,此代码(由SSE内在函数组成)也执行性能计数操作。当我为Win32编译相同的代码时,我遇到了这个操作的问题。

操作很简单:

LARGE_INTEGER Count;
QueryPerformanceCounter( &Count );
uint64_t v = Count.QuadPart;
printf( "%llu\n", v );
printf( "%f\n", (double) v ); 

第一个printf打印正确的64位值。第二个printf产生-1。#IND00。

如果我手动分配v,则错误消失。

检查代码是否针对可能的缓冲区/ overrun和未初始化的访问。不知道出了什么问题。 Win64上没有这样的错误。

编译器生成以下代码:在该块上:

;;; LARGE_INTEGER Count;
;;; QueryPerformanceCounter( &Count );
    lea       eax, DWORD PTR [1408+esp]                     ;152.1
    push      eax                                           ;152.1
    call      DWORD PTR [__imp__QueryPerformanceCounter@4]  ;152.1
                            ; LOE ebx esi
.B1.94:                     ; Preds .B1.93

;;; uint64_t v = Count.QuadPart;
    mov       eax, DWORD PTR [1408+esp]                     ;153.14
    mov       edi, DWORD PTR [1412+esp]                     ;153.14
    mov       DWORD PTR [24+esp], eax                       ;153.14

;;; printf( "%llu\n", v );
    push      edi                                           ;154.1
    push      eax                                           ;154.1
    push      OFFSET FLAT: ??_C@_05A@?$CFllu?6?$AA@         ;154.1
    call      _printf                                       ;154.1
                            ; LOE ebx esi edi
.B1.344:                    ; Preds .B1.94
    add       esp, 12                                       ;154.1
                            ; LOE ebx esi edi
.B1.95:                     ; Preds .B1.344

;;; printf( "%f\n", (double) v ); 
    mov       DWORD PTR [esp], OFFSET FLAT: ??_C@_03A@?$CFf?6?$AA@ ;155.1
    mov       eax, DWORD PTR [24+esp]                       ;155.1
    mov       DWORD PTR [32+esp], eax                       ;155.1
    mov       DWORD PTR [36+esp], edi                       ;155.1
    fild      QWORD PTR [32+esp]                            ;155.1
    shr       edi, 31                                       ;155.1
    fadd      QWORD PTR [_2il0floatpacket.1575+edi*8]       ;155.1
    fstp      QWORD PTR [4+esp]                             ;155.1
    call      _printf                                       ;155.1

但是,如果我在第二次printf后复制此部分:

QueryPerformanceCounter( &Count );
v = Count.QuadPart;
printf( "%f\n", (double) v );

printf打印正确的值。 汇编程序代码有点不同:

;;; QueryPerformanceCounter( &Count );
    lea       eax, DWORD PTR [1408+esp]                     ;156.1
    push      eax                                           ;156.1
    call      DWORD PTR [__imp__QueryPerformanceCounter@4]  ;156.1
                            ; LOE ebx esi
.B1.97:                         ; Preds .B1.96

;;; v = Count.QuadPart;
;;; printf( "%f\n", (double) v );
    fild      QWORD PTR [1408+esp]                          ;158.1
    mov       eax, DWORD PTR [1412+esp]                     ;158.1
    shr       eax, 31                                       ;158.1
    mov       DWORD PTR [esp], OFFSET FLAT: ??_C@_03A@?$CFf?6?$AA@ ;158.1
    fadd      QWORD PTR [_2il0floatpacket.1575+eax*8]       ;158.1
    fstp      QWORD PTR [4+esp]                             ;158.1
    call      _printf                                       ;158.1

1 个答案:

答案 0 :(得分:0)

找到解决方案:执行SSE计算后,应调用_mm_empty()函数。