gcc -O3 optimize :: xmm0 register?

时间:2013-10-27 06:26:20

标签: c optimization gcc sse

(我不能很好地使用英语..请理解T-T)

我正在编写一个vsprintf函数来使用我的64位操作系统内核(由C编写),并检查它在Visual Studio和Cygwin gcc中运行良好。 然后,我把我的内核运行起来......但是内核运行不正常

我调试并找出了问题:vsprintf包含下一个汇编代码

movdqa xmm0,XMMWORD PTR [rip+0x0]

真正的问题是我从不使用浮点!

我猜这是gcc的优化,似乎是正确的,因为它没有优化就能很好地运行

有没有任何解决方案,可以这么说,gcc选项禁用xmm寄存器的优化?

2 个答案:

答案 0 :(得分:7)

生成XMM寄存器移动指令,因为在System V AMD64 ABI中,浮点参数存储在XMM0-XMM7中。

由于我们不知道是否仅通过查看可变参数函数来使用浮点,因此编译器需要生成指令以将浮点值推送到va_list


您可以使用-mno-sse flag to disable SSE。例如,

__attribute__((noinline))
void f(const char* x, ...) {
    va_list va;
    va_start(va, x);
    vprintf(x, va);
    va_end(va);
}

没有-mno-sse标志:

subq    $0x000000d8,%rsp
testb   %al,%al
movq    %rsi,0x28(%rsp)
movq    %rdx,0x30(%rsp)
movq    %rcx,0x38(%rsp)
movq    %r8,0x40(%rsp)
movq    %r9,0x48(%rsp)
je  0x100000f1b
movaps  %xmm0,0x50(%rsp)
movaps  %xmm1,0x60(%rsp)
movaps  %xmm2,0x70(%rsp)
movaps  %xmm3,0x00000080(%rsp)
movaps  %xmm4,0x00000090(%rsp)
movaps  %xmm5,0x000000a0(%rsp)
movaps  %xmm6,0x000000b0(%rsp)
movaps  %xmm7,0x000000c0(%rsp)
0x100000f1b:
leaq    0x000000e0(%rsp),%rax
movl    $0x00000008,0x08(%rsp)
movq    %rax,0x10(%rsp)
leaq    0x08(%rsp),%rsi
leaq    0x20(%rsp),%rax
movl    $0x00000030,0x0c(%rsp)
movq    %rax,0x18(%rsp)
callq   0x100000f6a ; symbol stub for: _vprintf
addq    $0x000000d8,%rsp
ret

使用-mno-sse标志:

subq    $0x58,%rsp
leaq    0x60(%rsp),%rax
movq    %rsi,0x28(%rsp)
movq    %rax,0x10(%rsp)
leaq    0x08(%rsp),%rsi
leaq    0x20(%rsp),%rax
movq    %rdx,0x30(%rsp)
movq    %rcx,0x38(%rsp)
movq    %r8,0x40(%rsp)
movq    %r9,0x48(%rsp)
movl    $0x00000008,0x08(%rsp)
movq    %rax,0x18(%rsp)
callq   0x100000f6a ; symbol stub for: _vprintf
addq    $0x58,%rsp
ret

您也可以使用target attribute为该功能禁用SSE,例如

__attribute__((noinline, target("no-sse")))
//                       ^^^^^^^^^^^^^^^^
void f(const char* x, ...) {
    va_list va;
    va_start(va, x);
    vprintf(x, va);
    va_end(va);
}

但是请注意,其他具有SSE支持的函数不会知道f不使用SSE ,因此使用浮点数调用它们将导致未定义的行为< / EM>:

int main() {
    f("%g %g", 1.0, 2.0);  // 1.0 and 2.0 are stored in XMM0–1
                           // So this will print garbage e.g. `0 6.95326e-310`
}

答案 1 :(得分:0)

使用-O2而不是-O3它将起作用。