如何在x86-64上优化C和C++中的函数返回值?

jot*_*tik 12 c c++ performance x86-64 abi

所述X86-64 ABI指定两个返回寄存器:raxrdx,在大小两个64位(8个字节).

假设x86-64是唯一的目标平台,这两个功能中的哪一个:

uint64_t f(uint64_t * const secondReturnValue) {
    /* Calculate a and b. */
    *secondReturnValue = b;
    return a;
}

std::pair<uint64_t, uint64_t> g() {
    /* Calculate a and b, same as in f() above. */
    return { a, b };
}
Run Code Online (Sandbox Code Playgroud)

考虑到针对x86-64的C/C++编译器的当前状态,会产生更好的性能吗?使用一个版本或其他版本是否存在性能方面的任何陷阱?编译器(GCC,Clang)总是能够优化std::pair返回raxrdx吗?

更新:通常,如果编译器优化std::pair方法(使用GCC 5.3.0Clang 3.8.0的二进制输出示例),则返回一对更快.如果f()没有内联,编译器必须生成代码以将值写入内存,例如:

movq b, (%rdi)
movq a, %rax
retq
Run Code Online (Sandbox Code Playgroud)

但是如果g()编译器满足要求:

movq a, %rax
movq b, %rdx
retq
Run Code Online (Sandbox Code Playgroud)

因为将值写入内存的指令通常比将值写入寄存器的指令慢,所以第二个版本应该更快.

Bas*_*tch 8

由于ABI指定在某些特定情况下必须将两个寄存器用于2字结果,因此任何符合标准的编译器都必须遵守该规则.

但是,对于这些微小的功能,我猜大多数性能都来自内联.

您可能要编译和链接g++ -flto -O2使用链接时优化.

我想第二个函数(通过2个寄存器返回一对)可能会稍快一些,并且在某些情况下,GCC编译器可能会内联并优化第一个到第二个.

但如果你关心的话,你真的应该做基准测试.