用于简单构造函数的复杂编译器输出 [英] Complex compiler output for simple constructor

查看:110
本文介绍了用于简单构造函数的复杂编译器输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个64位整数成员的struct X和一个构造函数:

I have a struct X with two 64-bit integer members, and a constructor:

struct X
{
    X(uint64_t a, uint64_t b)
    {
        a_ = a; b_ = b;
    }

    uint64_t a_, b_;
};

当我查看编译器输出(在64位Linux上为x86-64 gcc 8.3和x86-64 clang 8.0.0)时,没有启用任何优化,我看到了以下针对构造函数的代码.

When I look at the compiler output (x86-64 gcc 8.3 and x86-64 clang 8.0.0, on 64-bit Linux), with no optimizations enabled, I see the following code for the constructor.

x86-64 gcc 8.3:

x86-64 gcc 8.3:

X::X(unsigned long, unsigned long):
    push    rbp
    mov     rbp, rsp
    mov     QWORD PTR [rbp-8], rdi
    mov     QWORD PTR [rbp-16], rsi
    mov     QWORD PTR [rbp-24], rdx
    mov     rax, QWORD PTR [rbp-8]
    mov     QWORD PTR [rax], 0
    mov     rax, QWORD PTR [rbp-8]
    mov     QWORD PTR [rax+8], 0
    mov     rax, QWORD PTR [rbp-8]
    mov     rdx, QWORD PTR [rbp-16]
    mov     QWORD PTR [rax+8], rdx
    mov     rax, QWORD PTR [rbp-8]
    mov     rdx, QWORD PTR [rbp-24]
    mov     QWORD PTR [rax], rdx
    nop
    pop     rbp
    ret

x86-64 clang 8.0.0:

x86-64 clang 8.0.0:

X::X(unsigned long, unsigned long):
    push    rbp
    mov     rbp, rsp
    mov     qword ptr [rbp - 8], rdi
    mov     qword ptr [rbp - 16], rsi
    mov     qword ptr [rbp - 24], rdx
    mov     rdx, qword ptr [rbp - 8]
    mov     qword ptr [rdx], 0
    mov     qword ptr [rdx + 8], 0
    mov     rsi, qword ptr [rbp - 16]
    mov     qword ptr [rdx + 8], rsi
    mov     rsi, qword ptr [rbp - 24]
    mov     qword ptr [rdx], rsi
    pop     rbp
    ret

有人知道为什么输出如此复杂吗?即使没有启用优化,我也希望有两个简单的"mov"语句.

Does anyone know why the output is so complex? I would have expected two simple "mov" statements, even with no optimizations enabled.

推荐答案

会发生什么,为什么?

如果不启用优化功能,编译器会将所有变量存储在堆栈中,而编译器会返回堆栈中的所有值.这样做的原因是,它使调试器可以更轻松地跟踪程序中正在发生的事情:他们可以观察程序的堆栈.

What happens, and why?

If you don't turn on optimizations, the compiler stores all variables on the stack, and the compiler returns all values on the stack. The reason it does this is that it makes it easier for debuggers to keep track of what's going on in the program: they can observe the program's stack.

此外,每个函数都必须在输入函数时更新栈指针,并在退出函数时重置栈指针.这也有利于调试器:调试器始终可以准确告诉您何时输入函数或退出函数.

In addition, every function has to update the stack pointer when the function's entered, and reset the stack pointer when the function is exited. This is also for the debugger's benefit: the debugger can always tell exactly when you enter a function or exit a function.

带有-O0的代码:

X::X(unsigned long, unsigned long):
    push    rbp        // Push the frame pointer to the stack
    mov     rbp, rsp   // Copy the frame pointer to the rsb register
    // Create the object (on the stack)
    mov     QWORD PTR [rbp-8], rdi  
    mov     QWORD PTR [rbp-16], rsi
    mov     QWORD PTR [rbp-24], rdx
    mov     rax, QWORD PTR [rbp-8]
    mov     rdx, QWORD PTR [rbp-16]
    mov     QWORD PTR [rax], rdx
    mov     rax, QWORD PTR [rbp-8]
    mov     rdx, QWORD PTR [rbp-24]
    mov     QWORD PTR [rax+8], rdx
    nop     // IDEK why it does this
    // Pop the frame pointer
    pop     rbp
    ret

带有-O1的代码:

X::X(unsigned long, unsigned long):
    mov     rax, rdi
    mov     rdx, rsi
    ret

这有关系吗?

种类.没有优化的代码会慢很多,特别是因为编译器必须执行此类操作.但是几乎没有理由启用优化.

gcc和clang都具有-Og选项:此选项打开不要干扰调试的所有优化.如果代码的调试版本运行缓慢,请尝试使用-Og进行编译.

Both gcc and clang have the -Og option: this option turns on all optimizations that don't interfere with debugging. If the debug version of the code is running slowly, try compiling it with -Og.

带有-Og的代码:

X::X(unsigned long, unsigned long):
    mov     rax, rdi
    mov     rdx, rsi
    ret

资源

有关-Og和其他使代码易于调试的选项的更多信息: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html

Resources

More information on -Og and other options to make code easy to debug: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html

有关优化和优化选项的更多信息: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

More information on optimization and optimization options: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

这篇关于用于简单构造函数的复杂编译器输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆