整个数组可以驻留在某些CPU寄存器中吗?

发布于 2024-10-01 11:34:52 字数 314 浏览 1 评论 0原文

由于我对 cpu 寄存器不太熟悉,一般来说,在任何体系结构中,特别是 x86 中,如果使用 VC++ 与编译器相关,我很好奇数组的所有元素是否都可以像数组一样具有少量元素1 字节字符和 4 个元素驻留在某个 cpu 寄存器中,因为我知道这对于双精度、整数等单个基元可能是正确的?

当我们有一个像下面这样的参数时:

void someFunc(char charArray[4]){
//whatever
}

这个参数传递是否肯定是通过将​​指针传递给函数来完成的,或者该数组将驻留在某个CPU寄存器中,从而无需将指针传递给主内存?

As I'm not too much familiar with cpu registers, in general and in any architecture specially x86 and if compiler-relevant using VC++ I'm curious that is it possible for all elements of an array with a tiny number of elements like an array of 1-byte characters with 4 elements to reside in some cpu register as I know this could be true for single primitives like double, integer, etc ?

when we have a parameter like below:

void someFunc(char charArray[4]){
//whatever
}

Will this parameter passing be definitely done through passing a pointer to the function or that array would be residing in some cpu register eliminating the need to pass a pointer to main memory?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

秋凉 2024-10-08 11:34:52

依赖于编译器,也不可能。数组不能像其他类型一样按值传递,即它们在传递到函数时不能被复制。 C++ 标准很明确,在处理声明中的函数签名时,以下是完全等价的:

void foo( char *a );
void foo( char a[] );
void foo( char a[4] );
void foo( char a[ 100000 ] );

兼容的编译器会将函数签名中的数组转换为指针。现在,在调用处,会发生类似的操作:如果参数是数组,编译器必须将其分解为指向第一个元素的指针。同样,数组的大小在衰减中丢失。

特定的寄存器可用于保存多个值并对它们执行操作(谷歌搜索向量化操作、MME 和变体)。但是,虽然这意味着编译器实际上可以将小数组的内容插入到单个寄存器中,但这不能用于更改您引用的函数调用。

This is not compiler dependent, nor is it possible. Arrays cannot be passed by value in the same way as other types, i.e. they cannot be copied when passed into a function. The C++ standard is clear in that when processing a function signature in a declaration the following are exact equivalencies:

void foo( char *a );
void foo( char a[] );
void foo( char a[4] );
void foo( char a[ 100000 ] );

A compliant compiler will convert the array in the function signature into a pointer. Now, at the place of call, a similar operation takes place: if the argument is an array, the compiler has to decay it into a pointer to the first element. Again, the size of the array is lost in the decay.

Specific registers can be used to hold more than one value and perform operations on them (google for vectorized operations, MME and variants). But while that means that the compiler can actually insert the contents of a small array into a single register, that cannot be used to change the function call that you refer to.

墨落画卷 2024-10-08 11:34:52

在单个函数中,只要编译器能够生成 CPU 指令来按照代码的指示操作数组,数组就可以保存在一个或多个寄存器中。该标准并没有真正定义寄存器中“存在”的含义。这是编译器和调试器之间的私人事务,并且寄存器中的某些内容与完全“优化掉”之间可能存在细微的界限。

在您的示例中,参数是一个指针,而不是一个数组(请参阅 dribeas 的答案)。因此,它指向的数组可能保存在寄存器中是不寻常的。您可能处理的“主”体系结构不允许指向寄存器的指针,因此即使数组保存在调用代码中的寄存器中,也必须将其写入内存才能获取指向寄存器的指针它,传递给被调用者。

如果函数调用是内联的,那么可能会有更好的优化,就像根本没有调用一样。

如果将数组包装在结构体中,则可以将其转换为可以按值传递的内容:

struct Foo {
    char a[4];
};

void FooFunc(Foo f) {
    // whatever
}

现在,该函数将实际的数组数据作为其参数,因此将其保存在寄存器中的障碍减少了。不过,实现的调用约定是否确实在寄存器中传递小结构是另一个问题。我不知道什么调用约定可以做到这一点(如果有的话)。

Within a single function, an array could be held in one or more registers, just so long as the compiler is able to produce CPU instructions to manipulate it as the code dictates. The standard doesn't really define what it means for something to "be" in a register. It's a private matter between the compiler and the debugger, and there may be a fine line between something being in a register, and being "optimized away" entirely.

In your example, the parameter is a pointer, not an array (see dribeas' answer). So it would be unusual that the array it points to could possibly be held a register. The "main" architectures that you probably deal with don't allow a pointer to a register, so even if the array was held in a register in the calling code, it would have to be written into memory in order to take a pointer to it, to pass to the callee.

If the function call was inlined, then better optimizations might be possible, just as if there were no call at all.

If you wrap your array in a struct, then you turn it into something that can be passed by value:

struct Foo {
    char a[4];
};

void FooFunc(Foo f) {
    // whatever
}

Now, the function is taking the actual array data as its parameter, so there's one less barrier to holding it in a register. Whether the implementation's calling convention actually does pass small structs in registers is another question, though. I don't know what calling conventions do this, if any.

つ低調成傷 2024-10-08 11:34:52

在我相当熟悉的 5 个左右编译器中,(Borland/Turbo C/C++ 从 1.0 开始,Watcom C/C++ 从 v8.0 开始,MSC 从 5.0 开始,IBM Visual Age C/C++,DOS 上各种版本的 gcc 、Linux 和 Windows)我还没有看到这种优化自然发生。

有一个字符串库,我不记得它的名字了,它在 x86 ASM 中做了类似的优化。它可能是“自发组装”库的一部分,但不能保证。

Out of the 5 or so compilers I'm fairly familiar with, (Borland/Turbo C/C++ from 1.0, Watcom C/C++ from v8.0, MSC from 5.0, IBM Visual Age C/C++, gcc of various versions on DOS, Linux and Windows) I've not seen this optimization happen naturally.

There was a string library, whose name I cannot remember, that did optimizations similar to this in x86 ASM. It may have been part of the "Spontaneous Assembly" library, but no guarantees.

不知在何时 2024-10-08 11:34:52

接受数组的函数可能会索引到该数组。据我所知,没有任何体系结构支持对寄存器进行有效索引,因此在寄存器中传递数组可能毫无意义。

(在 x86 架构上,您可以通过访问 alah 来访问 a[0]a[1] > eax 寄存器,但这是一种特殊情况,仅当索引在编译时已知时才有效。)

A function that accepts an array is probably going to index into that array. I know of no architecture that supports efficient indexing into a register, so it's probably pointless to pass arrays in registers.

(On an x86 architecture, you could access a[0] and a[1] by accessing al and ah of the eax register, but that is a special case that only works if the indexes are known at compile time.)

街道布景 2024-10-08 11:34:52

您询问在 x86 上使用 VC++ 是否可行。

我怀疑这种配置是否可行。确实,您可以生成将数组保存在寄存器中的汇编程序代码,但由于数组的性质,它绝不是编译器的自然优化,因此我怀疑他们是否将其放入其中。

您可以尝试一下并生成一些代码,编译器有“激励”将其放入寄存器中,但它看起来很奇怪,就像

char x[4];
*((int*)x) = 36587467;

使用优化和 /FA 开关编译它并查看生成的汇编代码(然后告诉我们结果:-))

如果您以更“自然”的方式使用它,例如访问单个字符或使用字符串初始化它,则编译器根本没有理由将该数组放入寄存器中。

即使将其传递给函数 - 编译器也可能会将数组的地址放入寄存器中,而不是数组本身

You asked if its possible with VC++ on an x86.

I doubt it's possible in that configuration. True, you could produce assembler code where that array is kept in a register, but due to the nature of arrays it would be by no means a natural optimization for a compiler, so I doubt they put it in.

You can try it out though and produce some code where the compiler would have an "incentive" to put it in a register, but it would look pretty weird like

char x[4];
*((int*)x) = 36587467;

Compile that with optimizations and the /FA switch and look at the assembler code produced (and then tell us the results :-))

If you use it in a more "natural" way, like accessing single characters or initializing it with a string there is no reason at all for the compiler to put that array into a register.

Even when passing it to a function - the compiler might put the address of the array into the register, but not the array itself

黎夕旧梦 2024-10-08 11:34:52

只有变量可以存储在寄存器中。您可以尝试使用 register 关键字强制寄存器存储: register int i;

数组默认是指针。

您可以像这样获取位于 4 位置的值(使用指针语法):

char c = *(charArray + 4);

Only variables can be stored in a register. You can try to force register storage by using the register keyword: register int i;

Arrays are by default pointers.

You can get the value located at the 4 position like this (using pointer syntax):

char c = *(charArray + 4);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文