Gcc -O3 optimize :: xmm0 register?

(I can't use English well .. please understand TT)

I wrote the vsprintf function to use my 64-bit OS kernel (written in C) and verified that it works well in Visual Studio and Cygwin gcc. Then I put in my kernel and run ... but the kernel does not work well

I debugged and figured out the problem: vsprintf contains the following build code

movdqa xmm0,XMMWORD PTR [rip+0x0] 

The real problem is that I NEVER use floating point!

I assume it was gcc optimization, and it seems correct because it works without optimization

Is there any solution, so to speak, a gcc option that disables optimization using xmm registers?

+6
source share
2 answers

XMM register move commands are created because, in System V AMD64 ABI , floating point arguments are stored in XMM0-XMM7.

Since we don’t know if floating points are used simply by looking at a variable function, the compiler must generate instructions to push the floating point values ​​to va_list .


You can use the -mno-sse to disable SSE . For instance,

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

Without the -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 

With the -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 

You can also use the target attribute to disable SSE only for this function, for example.

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

But be careful that other functions with SSE support will not know that f does not use SSE , and therefore calling them with floating point numbers will lead to undefined behavior:

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

use -O2 instead of -O3, it will work.

0
source

Source: https://habr.com/ru/post/956810/


All Articles