8

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

这种结构的样本:

struct sample{
 public:
  char char1;
  char char2;
};

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

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
4

4 回答 4

5

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

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

于 2010-11-18T09:17:52.633 回答
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 );

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

我从未见过一个编译器会自动执行此操作,而无需您告诉它,但它可能存在。

于 2010-11-18T09:28:58.790 回答
3

在某些架构上(比如 i386,我知道它很古老,但这就是我长大的东西;)将它传递到寄存器中当然是有意义的,因为从堆栈中推送和弹出需要更多时间(比如 3-6 次更多)CPU周期作为通过寄存器传递。因此,编译器会为此做好优化工作。

我可以想象还有其他架构无关紧要。或者,如果寄存器用于产生更多改进的其他优化,则为此使用它们是没有意义的。

您正在使用/定位什么架构,或者您在一般情况下询问?

于 2010-11-18T09:17:14.723 回答
1

我认为有些编译器会在寄存器中传递 POD,即使它们是structs.

于 2010-11-18T09:18:51.603 回答