繁体   English   中英

返回 Vs。 指针

[英]Returning Vs. Pointer

在这两种情况下,性能会有多大差异?

int func(int a, int b) { return a + b; }

void func(int a, int b, int * c) { *c = a + b; }

现在,如果它是一个结构呢?

typedef struct { int a; int b; char c; } my;

my func(int a, int b, char c) { my x; x.a = a; x.b = b; x.c = c; return x; }

void func(int a, int b, int c, my * x) { x->a = a; x->b = b; x->c = c; }

我能想到的一件事是寄存器不能用于此目的,对吗? 除此之外,我不知道这个函数在通过编译器后会怎样。

哪个更高效、更快捷?

如果函数可以内联,往往前2个没有区别。

否则(由于没有链接时优化而没有内联)按值返回int更有效,因为它只是可以立即使用的寄存器中的值 此外,调用者不必传递尽可能多的参数,也不必查找/腾出空间来指向。 如果调用者确实想要使用输出值,则必须重新加载它,从而在从准备好输入到准备好输出的整个依赖链中引入延迟。 (存储转发延迟在现代 x86 CPU 上约为 5 个周期,而lea eax, [rdi + rsi]为 1 个周期延迟,它将为 x86-64 System V 实现该功能。

例外情况可能是在极少数情况下,调用者不打算使用该值,只是希望它在内存中的某个地址。 将该地址传递给被调用者(在寄存器中)以便在那里使用它意味着调用者不必将该地址保留在任何可以在函数调用中幸存的地方。


对于结构版本:

寄存器不能用于此目的,对吗?

不,对于某些调用约定,可以在寄存器中返回小结构。

x86-64 System V 将按 RDX:RAX 寄存器对中的值返回您的my结构,因为它小于 16 个字节并且都是整数。 (并且可以简单地复制。)在https://godbolt.org/z/x73cEh上试试 -

# clang11.0 -O3 for x86-64 SysV
func_val:
        shl     rsi, 32
        mov     eax, edi
        or      rax, rsi             # (uint64_t)b<<32 | a;  the low 64 bits of the struct
    # c was already in EDX, the low half of RDX; clang leaves it there.
        ret
func_out:
        mov     dword ptr [rcx], edi
        mov     dword ptr [rcx + 4], esi        # just store the struct members 
        mov     byte ptr [rcx + 8], dl          # to memory pointed-to by 4th arg
        ret

GCC 不假设char c像 clang 那样正确地符号扩展到 EDX( 非官方 ABI 功能)。 GCC 做了一个非常愚蠢的字节存储/双字重载,它创建了一个存储转发停顿,从内存中而不是从 EDX 的高字节中获取未初始化的垃圾。 纯粹是一个错过的优化,但可以在https://godbolt.org/z/WGcqKc 中查看。 它还疯狂地使用 SSE2 将两个整数合并为 64 位值,然后再执行movq rax, xmm0或输出参数的内存。

如果调用者使用这些值,您肯定希望结构版本内联,因此可以优化这种打包到返回值寄存器中的操作。

函数如何实际返回 C 中的结构变量? 有一个更大结构的 ARM 示例:按值返回将隐藏的指针传递给调用者的返回值对象。 从那里开始,如果分配给转义分析无法证明是私有的东西,则可能需要由调用者复制它。 (例如通过一些指针)。 什么阻止使用函数参数作为隐藏指针?

还相关: 为什么不对类 MEMORY 类型执行尾调用优化?

C 编译器如何实现返回大型结构的函数? 指出 C 和 C++ 之间的代码生成可能不同。

我不知道如何解释在不了解 asm 和您关心的调用约定的情况下可以应用的任何一般经验法则。 通常通过引用传递/返回大型结构,但对于小型结构,它非常“取决于”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM