编译器在cpu寄存器中将这样的结构传递给函数是否有意义?

Poo*_*ria 8 c++ compiler-construction function parameter-passing cpu-registers

我想知道某种结构是否包含多个原语但其总大小小于或等于单个cpu寄存器的大小(如4字节寄存器),编译器是否有意义将它放入在通过值或引用函数传递它时,在其中一个4字节寄存器中,而不是在被调用堆栈上复制它或传递指针,并且通常在将多于一个原语传递给函数时一个数组或一个结构会传递到一个cpu寄存器中派上用场了吗?

这种结构的样本:

struct sample{
 public:
  char char1;
  char char2;
};
Run Code Online (Sandbox Code Playgroud)

将结构传递给函数的示例:

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
Run Code Online (Sandbox Code Playgroud)

Rud*_*udi 5

这是在执行环境的应用程序二进制接口(ABI)中定义的.调用函数时,标准没有说明处理器寄存器的任何内容,因此创建一个将小结构打包到单个处理器寄存器中的环境是合法的.

对于引用部分,它们很可能无论如何都作为指针传递,因为当在被调用函数内部引用引用的地址时,它必须解析为引用对象的地址.


Cra*_*rks 4

是的。许多编译器都有一个特殊的关键字或类型属性,您可以使用它们来指定应该在寄存器中而不是在堆栈上传递结构。它在具有许多寄存器和深度管道的处理器(例如 PowerPC)上更为常见,并且可以在将值写入内存然后立即将其读回导致管道停顿的架构中实现巨大的性能改进。

通常,您只会将它用于与本机寄存器大小相同的结构。特别是,它对于具有宽 SIMD 寄存器(一次可以传递 16 个字节或更多)的处理器非常有用。这将让您在一个寄存器上传递(例如)一个 4 维向量(四个浮点数)。AMD 的 System V是允许这样做的 x86 ABI 的一个示例。

一个不同的例子是 GCC 的 d64_abi 类型属性,它告诉 PowerPC 在可能的情况下在寄存器上传递结构,而不是在堆栈上。(这是达尔文 ABI的一部分)。

typedef struct {
    int          a;
    float        f;
    char         c;
} __attribute__ ((d64_abi)) Thingy;

Thingy foo( Thingy t );
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,对 Foo 的调用会将 Thingy 传递到一个浮点寄存器和两个 int 寄存器上,而不是将其写入堆栈并再次读取。返回值以相同的方式返回到寄存器。

我从未见过编译器可以自动执行此操作,而无需您告知,但可能存在这样的编译器。