函数参数的编译器优化

3

函数参数被放置在栈上,但编译器可以通过使用可选寄存器来优化此任务。如果只有1-2个参数,这种优化会很有意义,而不是当有256个参数时(虽然没有人想要拥有最大数量的参数)。

如何找出某个编译器(如gcc)的参数限制(参数数量),以确保使用此优化?


1
这取决于平台是否将函数参数(如果有的话,哪些参数)放在堆栈上。对于除了32位x86之外的所有内容,它总是“一些寄存器中的参数” - 只有(现在古老的)x86传统才会将它们放在堆栈上。 - FrankH.
1
你为什么想知道这个? - Oliver Charlesworth
6
参数传递并不是编译器优化的“选择”。参数如何传递取决于代码的互操作性需求。可以查看 stackoverflow 上的“调用约定”和/或“ABI”了解更多信息。在同一平台上存在多种调用约定(例如 __cdecl__fastcall__stdcall 等等)主要是 x86/DOS/Windows 特有的事情。 - FrankH.
@FrankH 感谢您指导我正确的方向,那正是我需要的。请将评论作为答案发布 :) - Milan
我不是赏金猎人,我只是为了好玩而阅读这个网站;-) - FrankH.
3个回答

5

函数参数被放置在堆栈上,但编译器可以通过使用可选寄存器来优化此任务。

正如FrankH在他的评论中所说,以及我在我的答案中要说的,系统的应用二进制接口决定了如何将参数传递给函数-这被称为该平台的调用约定。

复杂化问题的是,x86 32位实际上有几种。这是历史遗留问题,源于当Win32到来时,每个人都疯狂地做着不同的事情。

因此,是的,您可以通过以这种方式编写函数调用来“优化”,但不,您不应该这样做。您应该遵循您的平台的标准。因为诚实的事实是,堆栈访问速度可能并没有使您的代码变得非常缓慢,以至于您需要与系统中的其他人不兼容。

ABIs/标准调用约定的必要性是什么?在使用处理器寄存器、堆栈等方面,应用程序必须就什么意味着什么以及它们应该放在哪里达成一致。如果一个函数决定所有参数都在寄存器中,而另一个函数决定一些参数在堆栈上,它们如何相互操作?此外,您可能会遇到术语“scratch registers”,意思是“那些您不需要恢复的寄存器”。如果您调用一个期望保留某些寄存器的函数会发生什么?
无论如何,关于您所要求的内容,这里有一些ABI文档: 最后一段是我最喜欢的。引用它:
在旧的DOS操作系统时代,经常可以将来自不同供应商的开发工具组合使用,而几乎没有兼容性问题。随着32位Windows的出现,情况已经完全失控了。不同的编译器使用不同的数据表示、不同的函数调用约定和不同的对象文件格式。虽然静态链接库传统上被认为是特定于编译器的,但动态链接库(DLL)的广泛使用使得以二进制形式分发函数库变得更加普遍。
因此,无论你想通过修改函数调用方法来进行优化,都不要这样做。找到另一种优化的方法。对你的代码进行剖析。研究你的编译器优化(-OX),如果你认为它有帮助并转储汇编代码以检查是否真正那么关键。

2

对于公开可见的函数,这在ABI标准中有所说明。对于无法从外部引用的函数,所有情况都不确定。


0

如果你想了解编译器的细节,你需要阅读精细的手册。如果你很幸运,你会在函数调用约定的描述中找到答案。否则,对于像 gcc 这样的开源编译器,你可能需要阅读它的源代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接